1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/* |
4
|
|
|
Options: |
5
|
|
|
jetpack_options (array) |
6
|
|
|
An array of options. |
7
|
|
|
@see Jetpack_Options::get_option_names() |
8
|
|
|
|
9
|
|
|
jetpack_register (string) |
10
|
|
|
Temporary verification secrets. |
11
|
|
|
|
12
|
|
|
jetpack_activated (int) |
13
|
|
|
1: the plugin was activated normally |
14
|
|
|
2: the plugin was activated on this site because of a network-wide activation |
15
|
|
|
3: the plugin was auto-installed |
16
|
|
|
4: the plugin was manually disconnected (but is still installed) |
17
|
|
|
|
18
|
|
|
jetpack_active_modules (array) |
19
|
|
|
Array of active module slugs. |
20
|
|
|
|
21
|
|
|
jetpack_do_activate (bool) |
22
|
|
|
Flag for "activating" the plugin on sites where the activation hook never fired (auto-installs) |
23
|
|
|
*/ |
24
|
|
|
|
25
|
|
|
class Jetpack { |
26
|
|
|
public $xmlrpc_server = null; |
27
|
|
|
|
28
|
|
|
private $xmlrpc_verification = null; |
29
|
|
|
|
30
|
|
|
public $HTTP_RAW_POST_DATA = null; // copy of $GLOBALS['HTTP_RAW_POST_DATA'] |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @var array The handles of styles that are concatenated into jetpack.css |
34
|
|
|
*/ |
35
|
|
|
public $concatenated_style_handles = array( |
36
|
|
|
'jetpack-carousel', |
37
|
|
|
'grunion.css', |
38
|
|
|
'the-neverending-homepage', |
39
|
|
|
'jetpack_likes', |
40
|
|
|
'jetpack_related-posts', |
41
|
|
|
'sharedaddy', |
42
|
|
|
'jetpack-slideshow', |
43
|
|
|
'presentations', |
44
|
|
|
'jetpack-subscriptions', |
45
|
|
|
'tiled-gallery', |
46
|
|
|
'widget-conditions', |
47
|
|
|
'jetpack_display_posts_widget', |
48
|
|
|
'gravatar-profile-widget', |
49
|
|
|
'widget-grid-and-list', |
50
|
|
|
'jetpack-widgets', |
51
|
|
|
'goodreads-widget', |
52
|
|
|
'jetpack_social_media_icons_widget', |
53
|
|
|
); |
54
|
|
|
|
55
|
|
|
public $plugins_to_deactivate = array( |
56
|
|
|
'stats' => array( 'stats/stats.php', 'WordPress.com Stats' ), |
57
|
|
|
'shortlinks' => array( 'stats/stats.php', 'WordPress.com Stats' ), |
58
|
|
|
'sharedaddy' => array( 'sharedaddy/sharedaddy.php', 'Sharedaddy' ), |
59
|
|
|
'twitter-widget' => array( 'wickett-twitter-widget/wickett-twitter-widget.php', 'Wickett Twitter Widget' ), |
60
|
|
|
'after-the-deadline' => array( 'after-the-deadline/after-the-deadline.php', 'After The Deadline' ), |
61
|
|
|
'contact-form' => array( 'grunion-contact-form/grunion-contact-form.php', 'Grunion Contact Form' ), |
62
|
|
|
'contact-form' => array( 'mullet/mullet-contact-form.php', 'Mullet Contact Form' ), |
63
|
|
|
'custom-css' => array( 'safecss/safecss.php', 'WordPress.com Custom CSS' ), |
64
|
|
|
'random-redirect' => array( 'random-redirect/random-redirect.php', 'Random Redirect' ), |
65
|
|
|
'videopress' => array( 'video/video.php', 'VideoPress' ), |
66
|
|
|
'widget-visibility' => array( 'jetpack-widget-visibility/widget-visibility.php', 'Jetpack Widget Visibility' ), |
67
|
|
|
'widget-visibility' => array( 'widget-visibility-without-jetpack/widget-visibility-without-jetpack.php', 'Widget Visibility Without Jetpack' ), |
68
|
|
|
'sharedaddy' => array( 'jetpack-sharing/sharedaddy.php', 'Jetpack Sharing' ), |
69
|
|
|
'omnisearch' => array( 'jetpack-omnisearch/omnisearch.php', 'Jetpack Omnisearch' ), |
70
|
|
|
'gravatar-hovercards' => array( 'jetpack-gravatar-hovercards/gravatar-hovercards.php', 'Jetpack Gravatar Hovercards' ), |
71
|
|
|
'latex' => array( 'wp-latex/wp-latex.php', 'WP LaTeX' ) |
72
|
|
|
); |
73
|
|
|
|
74
|
|
|
public $capability_translations = array( |
75
|
|
|
'administrator' => 'manage_options', |
76
|
|
|
'editor' => 'edit_others_posts', |
77
|
|
|
'author' => 'publish_posts', |
78
|
|
|
'contributor' => 'edit_posts', |
79
|
|
|
'subscriber' => 'read', |
80
|
|
|
); |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Map of modules that have conflicts with plugins and should not be auto-activated |
84
|
|
|
* if the plugins are active. Used by filter_default_modules |
85
|
|
|
* |
86
|
|
|
* Plugin Authors: If you'd like to prevent a single module from auto-activating, |
87
|
|
|
* change `module-slug` and add this to your plugin: |
88
|
|
|
* |
89
|
|
|
* add_filter( 'jetpack_get_default_modules', 'my_jetpack_get_default_modules' ); |
90
|
|
|
* function my_jetpack_get_default_modules( $modules ) { |
91
|
|
|
* return array_diff( $modules, array( 'module-slug' ) ); |
92
|
|
|
* } |
93
|
|
|
* |
94
|
|
|
* @var array |
95
|
|
|
*/ |
96
|
|
|
private $conflicting_plugins = array( |
97
|
|
|
'comments' => array( |
98
|
|
|
'Intense Debate' => 'intensedebate/intensedebate.php', |
99
|
|
|
'Disqus' => 'disqus-comment-system/disqus.php', |
100
|
|
|
'Livefyre' => 'livefyre-comments/livefyre.php', |
101
|
|
|
'Comments Evolved for WordPress' => 'gplus-comments/comments-evolved.php', |
102
|
|
|
'Google+ Comments' => 'google-plus-comments/google-plus-comments.php', |
103
|
|
|
'WP-SpamShield Anti-Spam' => 'wp-spamshield/wp-spamshield.php', |
104
|
|
|
), |
105
|
|
|
'contact-form' => array( |
106
|
|
|
'Contact Form 7' => 'contact-form-7/wp-contact-form-7.php', |
107
|
|
|
'Gravity Forms' => 'gravityforms/gravityforms.php', |
108
|
|
|
'Contact Form Plugin' => 'contact-form-plugin/contact_form.php', |
109
|
|
|
'Easy Contact Forms' => 'easy-contact-forms/easy-contact-forms.php', |
110
|
|
|
'Fast Secure Contact Form' => 'si-contact-form/si-contact-form.php', |
111
|
|
|
), |
112
|
|
|
'minileven' => array( |
113
|
|
|
'WPtouch' => 'wptouch/wptouch.php', |
114
|
|
|
), |
115
|
|
|
'latex' => array( |
116
|
|
|
'LaTeX for WordPress' => 'latex/latex.php', |
117
|
|
|
'Youngwhans Simple Latex' => 'youngwhans-simple-latex/yw-latex.php', |
118
|
|
|
'Easy WP LaTeX' => 'easy-wp-latex-lite/easy-wp-latex-lite.php', |
119
|
|
|
'MathJax-LaTeX' => 'mathjax-latex/mathjax-latex.php', |
120
|
|
|
'Enable Latex' => 'enable-latex/enable-latex.php', |
121
|
|
|
'WP QuickLaTeX' => 'wp-quicklatex/wp-quicklatex.php', |
122
|
|
|
), |
123
|
|
|
'protect' => array( |
124
|
|
|
'Limit Login Attempts' => 'limit-login-attempts/limit-login-attempts.php', |
125
|
|
|
'Captcha' => 'captcha/captcha.php', |
126
|
|
|
'Brute Force Login Protection' => 'brute-force-login-protection/brute-force-login-protection.php', |
127
|
|
|
'Login Security Solution' => 'login-security-solution/login-security-solution.php', |
128
|
|
|
'WPSecureOps Brute Force Protect' => 'wpsecureops-bruteforce-protect/wpsecureops-bruteforce-protect.php', |
129
|
|
|
'BulletProof Security' => 'bulletproof-security/bulletproof-security.php', |
130
|
|
|
'SiteGuard WP Plugin' => 'siteguard/siteguard.php', |
131
|
|
|
'Security-protection' => 'security-protection/security-protection.php', |
132
|
|
|
'Login Security' => 'login-security/login-security.php', |
133
|
|
|
'Botnet Attack Blocker' => 'botnet-attack-blocker/botnet-attack-blocker.php', |
134
|
|
|
'Wordfence Security' => 'wordfence/wordfence.php', |
135
|
|
|
'All In One WP Security & Firewall' => 'all-in-one-wp-security-and-firewall/wp-security.php', |
136
|
|
|
'iThemes Security' => 'better-wp-security/better-wp-security.php', |
137
|
|
|
), |
138
|
|
|
'random-redirect' => array( |
139
|
|
|
'Random Redirect 2' => 'random-redirect-2/random-redirect.php', |
140
|
|
|
), |
141
|
|
|
'related-posts' => array( |
142
|
|
|
'YARPP' => 'yet-another-related-posts-plugin/yarpp.php', |
143
|
|
|
'WordPress Related Posts' => 'wordpress-23-related-posts-plugin/wp_related_posts.php', |
144
|
|
|
'nrelate Related Content' => 'nrelate-related-content/nrelate-related.php', |
145
|
|
|
'Contextual Related Posts' => 'contextual-related-posts/contextual-related-posts.php', |
146
|
|
|
'Related Posts for WordPress' => 'microkids-related-posts/microkids-related-posts.php', |
147
|
|
|
'outbrain' => 'outbrain/outbrain.php', |
148
|
|
|
'Shareaholic' => 'shareaholic/shareaholic.php', |
149
|
|
|
'Sexybookmarks' => 'sexybookmarks/shareaholic.php', |
150
|
|
|
), |
151
|
|
|
'sharedaddy' => array( |
152
|
|
|
'AddThis' => 'addthis/addthis_social_widget.php', |
153
|
|
|
'Add To Any' => 'add-to-any/add-to-any.php', |
154
|
|
|
'ShareThis' => 'share-this/sharethis.php', |
155
|
|
|
'Shareaholic' => 'shareaholic/shareaholic.php', |
156
|
|
|
), |
157
|
|
|
'verification-tools' => array( |
158
|
|
|
'WordPress SEO by Yoast' => 'wordpress-seo/wp-seo.php', |
159
|
|
|
'WordPress SEO Premium by Yoast' => 'wordpress-seo-premium/wp-seo-premium.php', |
160
|
|
|
'All in One SEO Pack' => 'all-in-one-seo-pack/all_in_one_seo_pack.php', |
161
|
|
|
), |
162
|
|
|
'widget-visibility' => array( |
163
|
|
|
'Widget Logic' => 'widget-logic/widget_logic.php', |
164
|
|
|
'Dynamic Widgets' => 'dynamic-widgets/dynamic-widgets.php', |
165
|
|
|
), |
166
|
|
|
'sitemaps' => array( |
167
|
|
|
'Google XML Sitemaps' => 'google-sitemap-generator/sitemap.php', |
168
|
|
|
'Better WordPress Google XML Sitemaps' => 'bwp-google-xml-sitemaps/bwp-simple-gxs.php', |
169
|
|
|
'Google XML Sitemaps for qTranslate' => 'google-xml-sitemaps-v3-for-qtranslate/sitemap.php', |
170
|
|
|
'XML Sitemap & Google News feeds' => 'xml-sitemap-feed/xml-sitemap.php', |
171
|
|
|
'Google Sitemap by BestWebSoft' => 'google-sitemap-plugin/google-sitemap-plugin.php', |
172
|
|
|
'WordPress SEO by Yoast' => 'wordpress-seo/wp-seo.php', |
173
|
|
|
'WordPress SEO Premium by Yoast' => 'wordpress-seo-premium/wp-seo-premium.php', |
174
|
|
|
'All in One SEO Pack' => 'all-in-one-seo-pack/all_in_one_seo_pack.php', |
175
|
|
|
'Sitemap' => 'sitemap/sitemap.php', |
176
|
|
|
'Simple Wp Sitemap' => 'simple-wp-sitemap/simple-wp-sitemap.php', |
177
|
|
|
'Simple Sitemap' => 'simple-sitemap/simple-sitemap.php', |
178
|
|
|
'XML Sitemaps' => 'xml-sitemaps/xml-sitemaps.php', |
179
|
|
|
'MSM Sitemaps' => 'msm-sitemap/msm-sitemap.php', |
180
|
|
|
), |
181
|
|
|
); |
182
|
|
|
|
183
|
|
|
/** |
184
|
|
|
* Plugins for which we turn off our Facebook OG Tags implementation. |
185
|
|
|
* |
186
|
|
|
* Note: WordPress SEO by Yoast and WordPress SEO Premium by Yoast automatically deactivate |
187
|
|
|
* Jetpack's Open Graph tags via filter when their Social Meta modules are active. |
188
|
|
|
* |
189
|
|
|
* Plugin authors: If you'd like to prevent Jetpack's Open Graph tag generation in your plugin, you can do so via this filter: |
190
|
|
|
* add_filter( 'jetpack_enable_open_graph', '__return_false' ); |
191
|
|
|
*/ |
192
|
|
|
private $open_graph_conflicting_plugins = array( |
193
|
|
|
'2-click-socialmedia-buttons/2-click-socialmedia-buttons.php', |
194
|
|
|
// 2 Click Social Media Buttons |
195
|
|
|
'add-link-to-facebook/add-link-to-facebook.php', // Add Link to Facebook |
196
|
|
|
'add-meta-tags/add-meta-tags.php', // Add Meta Tags |
197
|
|
|
'easy-facebook-share-thumbnails/esft.php', // Easy Facebook Share Thumbnail |
198
|
|
|
'facebook/facebook.php', // Facebook (official plugin) |
199
|
|
|
'facebook-awd/AWD_facebook.php', // Facebook AWD All in one |
200
|
|
|
'facebook-featured-image-and-open-graph-meta-tags/fb-featured-image.php', |
201
|
|
|
// Facebook Featured Image & OG Meta Tags |
202
|
|
|
'facebook-meta-tags/facebook-metatags.php', // Facebook Meta Tags |
203
|
|
|
'wonderm00ns-simple-facebook-open-graph-tags/wonderm00n-open-graph.php', |
204
|
|
|
// Facebook Open Graph Meta Tags for WordPress |
205
|
|
|
'facebook-revised-open-graph-meta-tag/index.php', // Facebook Revised Open Graph Meta Tag |
206
|
|
|
'facebook-thumb-fixer/_facebook-thumb-fixer.php', // Facebook Thumb Fixer |
207
|
|
|
'facebook-and-digg-thumbnail-generator/facebook-and-digg-thumbnail-generator.php', |
208
|
|
|
// Fedmich's Facebook Open Graph Meta |
209
|
|
|
'header-footer/plugin.php', // Header and Footer |
210
|
|
|
'network-publisher/networkpub.php', // Network Publisher |
211
|
|
|
'nextgen-facebook/nextgen-facebook.php', // NextGEN Facebook OG |
212
|
|
|
'social-networks-auto-poster-facebook-twitter-g/NextScripts_SNAP.php', |
213
|
|
|
// NextScripts SNAP |
214
|
|
|
'opengraph/opengraph.php', // Open Graph |
215
|
|
|
'open-graph-protocol-framework/open-graph-protocol-framework.php', |
216
|
|
|
// Open Graph Protocol Framework |
217
|
|
|
'seo-facebook-comments/seofacebook.php', // SEO Facebook Comments |
218
|
|
|
'seo-ultimate/seo-ultimate.php', // SEO Ultimate |
219
|
|
|
'sexybookmarks/sexy-bookmarks.php', // Shareaholic |
220
|
|
|
'shareaholic/sexy-bookmarks.php', // Shareaholic |
221
|
|
|
'sharepress/sharepress.php', // SharePress |
222
|
|
|
'simple-facebook-connect/sfc.php', // Simple Facebook Connect |
223
|
|
|
'social-discussions/social-discussions.php', // Social Discussions |
224
|
|
|
'social-sharing-toolkit/social_sharing_toolkit.php', // Social Sharing Toolkit |
225
|
|
|
'socialize/socialize.php', // Socialize |
226
|
|
|
'only-tweet-like-share-and-google-1/tweet-like-plusone.php', |
227
|
|
|
// Tweet, Like, Google +1 and Share |
228
|
|
|
'wordbooker/wordbooker.php', // Wordbooker |
229
|
|
|
'wpsso/wpsso.php', // WordPress Social Sharing Optimization |
230
|
|
|
'wp-caregiver/wp-caregiver.php', // WP Caregiver |
231
|
|
|
'wp-facebook-like-send-open-graph-meta/wp-facebook-like-send-open-graph-meta.php', |
232
|
|
|
// WP Facebook Like Send & Open Graph Meta |
233
|
|
|
'wp-facebook-open-graph-protocol/wp-facebook-ogp.php', // WP Facebook Open Graph protocol |
234
|
|
|
'wp-ogp/wp-ogp.php', // WP-OGP |
235
|
|
|
'zoltonorg-social-plugin/zosp.php', // Zolton.org Social Plugin |
236
|
|
|
'wp-fb-share-like-button/wp_fb_share-like_widget.php' // WP Facebook Like Button |
237
|
|
|
); |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* Plugins for which we turn off our Twitter Cards Tags implementation. |
241
|
|
|
*/ |
242
|
|
|
private $twitter_cards_conflicting_plugins = array( |
243
|
|
|
// 'twitter/twitter.php', // The official one handles this on its own. |
244
|
|
|
// // https://github.com/twitter/wordpress/blob/master/src/Twitter/WordPress/Cards/Compatibility.php |
245
|
|
|
'eewee-twitter-card/index.php', // Eewee Twitter Card |
246
|
|
|
'ig-twitter-cards/ig-twitter-cards.php', // IG:Twitter Cards |
247
|
|
|
'jm-twitter-cards/jm-twitter-cards.php', // JM Twitter Cards |
248
|
|
|
'kevinjohn-gallagher-pure-web-brilliants-social-graph-twitter-cards-extention/kevinjohn_gallagher___social_graph_twitter_output.php', |
249
|
|
|
// Pure Web Brilliant's Social Graph Twitter Cards Extension |
250
|
|
|
'twitter-cards/twitter-cards.php', // Twitter Cards |
251
|
|
|
'twitter-cards-meta/twitter-cards-meta.php', // Twitter Cards Meta |
252
|
|
|
'wp-twitter-cards/twitter_cards.php', // WP Twitter Cards |
253
|
|
|
); |
254
|
|
|
|
255
|
|
|
/** |
256
|
|
|
* Message to display in admin_notice |
257
|
|
|
* @var string |
258
|
|
|
*/ |
259
|
|
|
public $message = ''; |
260
|
|
|
|
261
|
|
|
/** |
262
|
|
|
* Error to display in admin_notice |
263
|
|
|
* @var string |
264
|
|
|
*/ |
265
|
|
|
public $error = ''; |
266
|
|
|
|
267
|
|
|
/** |
268
|
|
|
* Modules that need more privacy description. |
269
|
|
|
* @var string |
270
|
|
|
*/ |
271
|
|
|
public $privacy_checks = ''; |
272
|
|
|
|
273
|
|
|
/** |
274
|
|
|
* Stats to record once the page loads |
275
|
|
|
* |
276
|
|
|
* @var array |
277
|
|
|
*/ |
278
|
|
|
public $stats = array(); |
279
|
|
|
|
280
|
|
|
/** |
281
|
|
|
* Allows us to build a temporary security report |
282
|
|
|
* |
283
|
|
|
* @var array |
284
|
|
|
*/ |
285
|
|
|
static $security_report = array(); |
|
|
|
|
286
|
|
|
|
287
|
|
|
/** |
288
|
|
|
* Jetpack_Sync object |
289
|
|
|
*/ |
290
|
|
|
public $sync; |
291
|
|
|
|
292
|
|
|
/** |
293
|
|
|
* Verified data for JSON authorization request |
294
|
|
|
*/ |
295
|
|
|
public $json_api_authorization_request = array(); |
296
|
|
|
|
297
|
|
|
/** |
298
|
|
|
* Holds the singleton instance of this class |
299
|
|
|
* @since 2.3.3 |
300
|
|
|
* @var Jetpack |
301
|
|
|
*/ |
302
|
|
|
static $instance = false; |
|
|
|
|
303
|
|
|
|
304
|
|
|
/** |
305
|
|
|
* Singleton |
306
|
|
|
* @static |
307
|
|
|
*/ |
308
|
|
|
public static function init() { |
309
|
|
|
if ( ! self::$instance ) { |
310
|
|
|
if ( did_action( 'plugins_loaded' ) ) |
311
|
|
|
self::plugin_textdomain(); |
312
|
|
|
else |
313
|
|
|
add_action( 'plugins_loaded', array( __CLASS__, 'plugin_textdomain' ), 99 ); |
314
|
|
|
|
315
|
|
|
self::$instance = new Jetpack; |
316
|
|
|
|
317
|
|
|
self::$instance->plugin_upgrade(); |
318
|
|
|
|
319
|
|
|
add_action( 'init', array( __CLASS__, 'perform_security_reporting' ) ); |
320
|
|
|
|
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
return self::$instance; |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
/** |
327
|
|
|
* Must never be called statically |
328
|
|
|
*/ |
329
|
|
|
function plugin_upgrade() { |
330
|
|
|
// Upgrade: 1.1 -> 1.2 |
331
|
|
|
if ( get_option( 'jetpack_id' ) ) { |
332
|
|
|
// Move individual jetpack options to single array of options |
333
|
|
|
$options = array(); |
334
|
|
|
foreach ( Jetpack_Options::get_option_names() as $option ) { |
335
|
|
|
if ( false !== $value = get_option( "jetpack_$option" ) ) { |
336
|
|
|
$options[$option] = $value; |
337
|
|
|
} |
338
|
|
|
} |
339
|
|
|
|
340
|
|
|
if ( $options ) { |
|
|
|
|
341
|
|
|
Jetpack_Options::update_options( $options ); |
342
|
|
|
|
343
|
|
|
foreach ( array_keys( $options ) as $option ) { |
344
|
|
|
delete_option( "jetpack_$option" ); |
345
|
|
|
} |
346
|
|
|
} |
347
|
|
|
|
348
|
|
|
// Add missing version and old_version options |
349
|
|
View Code Duplication |
if ( ! $version = Jetpack_Options::get_option( 'version' ) ) { |
350
|
|
|
$version = $old_version = '1.1:' . time(); |
351
|
|
|
/** |
352
|
|
|
* Fires on update, before bumping version numbers up to a new version. |
353
|
|
|
* |
354
|
|
|
* @since 3.4.0 |
355
|
|
|
* |
356
|
|
|
* @param string $version Jetpack version number. |
357
|
|
|
* @param bool false Does an old version exist. Default is false. |
358
|
|
|
*/ |
359
|
|
|
do_action( 'updating_jetpack_version', $version, false ); |
360
|
|
|
Jetpack_Options::update_options( compact( 'version', 'old_version' ) ); |
361
|
|
|
} |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
// Upgrade from a single user token to a user_id-indexed array and a master_user ID |
365
|
|
|
if ( ! Jetpack_Options::get_option( 'user_tokens' ) ) { |
366
|
|
|
if ( $user_token = Jetpack_Options::get_option( 'user_token' ) ) { |
367
|
|
|
$token_parts = explode( '.', $user_token ); |
368
|
|
|
if ( isset( $token_parts[2] ) ) { |
369
|
|
|
$master_user = $token_parts[2]; |
370
|
|
|
$user_tokens = array( $master_user => $user_token ); |
371
|
|
|
Jetpack_Options::update_options( compact( 'master_user', 'user_tokens' ) ); |
372
|
|
|
Jetpack_Options::delete_option( 'user_token' ); |
373
|
|
|
} else { |
374
|
|
|
// @todo: is this even possible? |
|
|
|
|
375
|
|
|
trigger_error( sprintf( 'Jetpack::plugin_upgrade found no user_id in user_token "%s"', $user_token ), E_USER_WARNING ); |
376
|
|
|
} |
377
|
|
|
} |
378
|
|
|
} |
379
|
|
|
|
380
|
|
|
// Clean up legacy G+ Authorship data. |
381
|
|
|
if ( get_option( 'gplus_authors' ) ) { |
382
|
|
|
delete_option( 'gplus_authors' ); |
383
|
|
|
delete_option( 'hide_gplus' ); |
384
|
|
|
delete_metadata( 'post', 0, 'gplus_authorship_disabled', null, true ); |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
if ( ! get_option( 'jetpack_private_options' ) ) { |
388
|
|
|
$jetpack_options = get_option( 'jetpack_options', array() ); |
389
|
|
|
foreach( Jetpack_Options::get_option_names( 'private' ) as $option_name ) { |
390
|
|
|
if ( isset( $jetpack_options[ $option_name ] ) ) { |
391
|
|
|
Jetpack_Options::update_option( $option_name, $jetpack_options[ $option_name ] ); |
392
|
|
|
unset( $jetpack_options[ $option_name ] ); |
393
|
|
|
} |
394
|
|
|
} |
395
|
|
|
update_option( 'jetpack_options', $jetpack_options ); |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
if ( Jetpack::is_active() ) { |
399
|
|
|
list( $version ) = explode( ':', Jetpack_Options::get_option( 'version' ) ); |
400
|
|
|
if ( JETPACK__VERSION != $version ) { |
401
|
|
|
add_action( 'init', array( __CLASS__, 'activate_new_modules' ) ); |
402
|
|
|
/** |
403
|
|
|
* Fires when synchronizing all registered options and constants. |
404
|
|
|
* |
405
|
|
|
* @since 3.3.0 |
406
|
|
|
*/ |
407
|
|
|
do_action( 'jetpack_sync_all_registered_options' ); |
408
|
|
|
} |
409
|
|
|
|
410
|
|
|
//if Jetpack is connected check if jetpack_unique_connection exists and if not then set it |
411
|
|
|
$jetpack_unique_connection = get_option( 'jetpack_unique_connection' ); |
412
|
|
|
$is_unique_connection = $jetpack_unique_connection && array_key_exists( 'version', $jetpack_unique_connection ); |
413
|
|
|
if ( ! $is_unique_connection ) { |
414
|
|
|
$jetpack_unique_connection = array( |
415
|
|
|
'connected' => 1, |
416
|
|
|
'disconnected' => -1, |
417
|
|
|
'version' => '3.6.1' |
418
|
|
|
); |
419
|
|
|
update_option( 'jetpack_unique_connection', $jetpack_unique_connection ); |
420
|
|
|
} |
421
|
|
|
} |
422
|
|
|
|
423
|
|
|
if ( get_option( 'jetpack_json_api_full_management' ) ) { |
424
|
|
|
delete_option( 'jetpack_json_api_full_management' ); |
425
|
|
|
self::activate_manage(); |
426
|
|
|
} |
427
|
|
|
|
428
|
|
|
} |
429
|
|
|
|
430
|
|
|
static function activate_manage( ) { |
431
|
|
|
|
432
|
|
|
if ( did_action( 'init' ) || current_filter() == 'init' ) { |
433
|
|
|
self::activate_module( 'manage', false, false ); |
434
|
|
|
} else if ( ! has_action( 'init' , array( __CLASS__, 'activate_manage' ) ) ) { |
435
|
|
|
add_action( 'init', array( __CLASS__, 'activate_manage' ) ); |
436
|
|
|
} |
437
|
|
|
|
438
|
|
|
} |
439
|
|
|
|
440
|
|
|
/** |
441
|
|
|
* Constructor. Initializes WordPress hooks |
442
|
|
|
*/ |
443
|
|
|
private function __construct() { |
444
|
|
|
/* |
445
|
|
|
* Check for and alert any deprecated hooks |
446
|
|
|
*/ |
447
|
|
|
add_action( 'init', array( $this, 'deprecated_hooks' ) ); |
448
|
|
|
|
449
|
|
|
/* |
450
|
|
|
* Do things that should run even in the network admin |
451
|
|
|
* here, before we potentially fail out. |
452
|
|
|
*/ |
453
|
|
|
add_filter( 'jetpack_require_lib_dir', array( $this, 'require_lib_dir' ) ); |
454
|
|
|
|
455
|
|
|
/** |
456
|
|
|
* We need sync object even in Multisite mode |
457
|
|
|
*/ |
458
|
|
|
$this->sync = new Jetpack_Sync; |
459
|
|
|
|
460
|
|
|
/** |
461
|
|
|
* Trigger a wp_version sync when updating WP versions |
462
|
|
|
**/ |
463
|
|
|
add_action( 'upgrader_process_complete', array( 'Jetpack', 'update_get_wp_version' ), 10, 2 ); |
464
|
|
|
$this->sync->mock_option( 'wp_version', array( 'Jetpack', 'get_wp_version' ) ); |
465
|
|
|
|
466
|
|
|
add_action( 'init', array( $this, 'sync_update_data') ); |
467
|
|
|
add_action( 'init', array( $this, 'sync_theme_data' ) ); |
468
|
|
|
|
469
|
|
|
/* |
470
|
|
|
* Load things that should only be in Network Admin. |
471
|
|
|
* |
472
|
|
|
* For now blow away everything else until a more full |
473
|
|
|
* understanding of what is needed at the network level is |
474
|
|
|
* available |
475
|
|
|
*/ |
476
|
|
|
if( is_multisite() ) { |
477
|
|
|
Jetpack_Network::init(); |
478
|
|
|
|
479
|
|
|
// Only sync this info if we are on a multi site |
480
|
|
|
// @since 3.7 |
481
|
|
|
$this->sync->mock_option( 'network_name', array( 'Jetpack', 'network_name' ) ); |
482
|
|
|
$this->sync->mock_option( 'network_allow_new_registrations', array( 'Jetpack', 'network_allow_new_registrations' ) ); |
483
|
|
|
$this->sync->mock_option( 'network_add_new_users', array( 'Jetpack', 'network_add_new_users' ) ); |
484
|
|
|
$this->sync->mock_option( 'network_site_upload_space', array( 'Jetpack', 'network_site_upload_space' ) ); |
485
|
|
|
$this->sync->mock_option( 'network_upload_file_types', array( 'Jetpack', 'network_upload_file_types' ) ); |
486
|
|
|
$this->sync->mock_option( 'network_enable_administration_menus', array( 'Jetpack', 'network_enable_administration_menus' ) ); |
487
|
|
|
|
488
|
|
|
if( is_network_admin() ) { |
489
|
|
|
// Sync network site data if it is updated or not. |
490
|
|
|
add_action( 'update_wpmu_options', array( $this, 'update_jetpack_network_settings' ) ); |
491
|
|
|
return; // End here to prevent single site actions from firing |
492
|
|
|
} |
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
|
496
|
|
|
$theme_slug = get_option( 'stylesheet' ); |
497
|
|
|
|
498
|
|
|
|
499
|
|
|
// Modules should do Jetpack_Sync::sync_options( __FILE__, $option, ... ); instead |
500
|
|
|
// We access the "internal" method here only because the Jetpack object isn't instantiated yet |
501
|
|
|
$this->sync->options( |
502
|
|
|
JETPACK__PLUGIN_DIR . 'jetpack.php', |
503
|
|
|
'home', |
504
|
|
|
'siteurl', |
505
|
|
|
'blogname', |
506
|
|
|
'gmt_offset', |
507
|
|
|
'timezone_string', |
508
|
|
|
'security_report', |
509
|
|
|
'stylesheet', |
510
|
|
|
"theme_mods_{$theme_slug}", |
511
|
|
|
'jetpack_sync_non_public_post_stati', |
512
|
|
|
'jetpack_options', |
513
|
|
|
'site_icon', // (int) - ID of core's Site Icon attachment ID |
514
|
|
|
'default_post_format', |
515
|
|
|
'default_category', |
516
|
|
|
'large_size_w', |
517
|
|
|
'large_size_h', |
518
|
|
|
'thumbnail_size_w', |
519
|
|
|
'thumbnail_size_h', |
520
|
|
|
'medium_size_w', |
521
|
|
|
'medium_size_h', |
522
|
|
|
'thumbnail_crop', |
523
|
|
|
'image_default_link_type' |
524
|
|
|
); |
525
|
|
|
|
526
|
|
|
foreach( Jetpack_Options::get_option_names( 'non-compact' ) as $option ) { |
527
|
|
|
$this->sync->options( __FILE__, 'jetpack_' . $option ); |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
/** |
531
|
|
|
* Sometimes you want to sync data to .com without adding options to .org sites. |
532
|
|
|
* The mock option allows you to do just that. |
533
|
|
|
*/ |
534
|
|
|
$this->sync->mock_option( 'is_main_network', array( $this, 'is_main_network_option' ) ); |
535
|
|
|
$this->sync->mock_option( 'is_multi_site', array( $this, 'is_multisite' ) ); |
536
|
|
|
$this->sync->mock_option( 'main_network_site', array( $this, 'jetpack_main_network_site_option' ) ); |
537
|
|
|
$this->sync->mock_option( 'single_user_site', array( 'Jetpack', 'is_single_user_site' ) ); |
538
|
|
|
$this->sync->mock_option( 'stat_data', array( $this, 'get_stat_data' ) ); |
539
|
|
|
|
540
|
|
|
$this->sync->mock_option( 'has_file_system_write_access', array( 'Jetpack', 'file_system_write_access' ) ); |
541
|
|
|
$this->sync->mock_option( 'is_version_controlled', array( 'Jetpack', 'is_version_controlled' ) ); |
542
|
|
|
$this->sync->mock_option( 'max_upload_size', 'wp_max_upload_size' ); |
543
|
|
|
$this->sync->mock_option( 'content_width', array( 'Jetpack', 'get_content_width' ) ); |
544
|
|
|
|
545
|
|
|
/** |
546
|
|
|
* Trigger an update to the main_network_site when we update the blogname of a site. |
547
|
|
|
* |
548
|
|
|
*/ |
549
|
|
|
add_action( 'update_option_siteurl', array( $this, 'update_jetpack_main_network_site_option' ) ); |
550
|
|
|
|
551
|
|
|
add_action( 'update_option', array( $this, 'log_settings_change' ), 10, 3 ); |
552
|
|
|
|
553
|
|
|
// Update the settings everytime the we register a new user to the site or we delete a user. |
554
|
|
|
add_action( 'user_register', array( $this, 'is_single_user_site_invalidate' ) ); |
555
|
|
|
add_action( 'deleted_user', array( $this, 'is_single_user_site_invalidate' ) ); |
556
|
|
|
|
557
|
|
|
// Unlink user before deleting the user from .com |
558
|
|
|
add_action( 'deleted_user', array( $this, 'unlink_user' ), 10, 1 ); |
559
|
|
|
add_action( 'remove_user_from_blog', array( $this, 'unlink_user' ), 10, 1 ); |
560
|
|
|
|
561
|
|
|
if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST && isset( $_GET['for'] ) && 'jetpack' == $_GET['for'] ) { |
562
|
|
|
@ini_set( 'display_errors', false ); // Display errors can cause the XML to be not well formed. |
|
|
|
|
563
|
|
|
|
564
|
|
|
require_once JETPACK__PLUGIN_DIR . 'class.jetpack-xmlrpc-server.php'; |
565
|
|
|
$this->xmlrpc_server = new Jetpack_XMLRPC_Server(); |
566
|
|
|
|
567
|
|
|
$this->require_jetpack_authentication(); |
568
|
|
|
|
569
|
|
|
if ( Jetpack::is_active() ) { |
570
|
|
|
// Hack to preserve $HTTP_RAW_POST_DATA |
571
|
|
|
add_filter( 'xmlrpc_methods', array( $this, 'xmlrpc_methods' ) ); |
572
|
|
|
|
573
|
|
|
$signed = $this->verify_xml_rpc_signature(); |
574
|
|
|
if ( $signed && ! is_wp_error( $signed ) ) { |
575
|
|
|
// The actual API methods. |
576
|
|
|
add_filter( 'xmlrpc_methods', array( $this->xmlrpc_server, 'xmlrpc_methods' ) ); |
577
|
|
|
} else { |
578
|
|
|
add_filter( 'xmlrpc_methods', '__return_empty_array' ); |
579
|
|
|
} |
580
|
|
|
} else { |
581
|
|
|
// The bootstrap API methods. |
582
|
|
|
add_filter( 'xmlrpc_methods', array( $this->xmlrpc_server, 'bootstrap_xmlrpc_methods' ) ); |
583
|
|
|
} |
584
|
|
|
|
585
|
|
|
// Now that no one can authenticate, and we're whitelisting all XML-RPC methods, force enable_xmlrpc on. |
586
|
|
|
add_filter( 'pre_option_enable_xmlrpc', '__return_true' ); |
587
|
|
|
} elseif ( is_admin() && isset( $_POST['action'] ) && 'jetpack_upload_file' == $_POST['action'] ) { |
588
|
|
|
$this->require_jetpack_authentication(); |
589
|
|
|
$this->add_remote_request_handlers(); |
590
|
|
|
} else { |
591
|
|
|
if ( Jetpack::is_active() ) { |
592
|
|
|
add_action( 'login_form_jetpack_json_api_authorization', array( &$this, 'login_form_json_api_authorization' ) ); |
593
|
|
|
add_filter( 'xmlrpc_methods', array( $this, 'public_xmlrpc_methods' ) ); |
594
|
|
|
} |
595
|
|
|
} |
596
|
|
|
|
597
|
|
|
if ( Jetpack::is_active() ) { |
598
|
|
|
Jetpack_Heartbeat::init(); |
599
|
|
|
} |
600
|
|
|
|
601
|
|
|
add_action( 'jetpack_clean_nonces', array( 'Jetpack', 'clean_nonces' ) ); |
602
|
|
|
if ( ! wp_next_scheduled( 'jetpack_clean_nonces' ) ) { |
603
|
|
|
wp_schedule_event( time(), 'hourly', 'jetpack_clean_nonces' ); |
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
add_filter( 'xmlrpc_blog_options', array( $this, 'xmlrpc_options' ) ); |
607
|
|
|
|
608
|
|
|
add_action( 'admin_init', array( $this, 'admin_init' ) ); |
609
|
|
|
add_action( 'admin_init', array( $this, 'dismiss_jetpack_notice' ) ); |
610
|
|
|
|
611
|
|
|
add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) ); |
612
|
|
|
|
613
|
|
|
add_action( 'wp_dashboard_setup', array( $this, 'wp_dashboard_setup' ) ); |
614
|
|
|
// Filter the dashboard meta box order to swap the new one in in place of the old one. |
615
|
|
|
add_filter( 'get_user_option_meta-box-order_dashboard', array( $this, 'get_user_option_meta_box_order_dashboard' ) ); |
616
|
|
|
|
617
|
|
|
add_action( 'wp_ajax_jetpack-sync-reindex-trigger', array( $this, 'sync_reindex_trigger' ) ); |
618
|
|
|
add_action( 'wp_ajax_jetpack-sync-reindex-status', array( $this, 'sync_reindex_status' ) ); |
619
|
|
|
|
620
|
|
|
// Jump Start AJAX callback function |
621
|
|
|
add_action( 'wp_ajax_jetpack_jumpstart_ajax', array( $this, 'jetpack_jumpstart_ajax_callback' ) ); |
622
|
|
|
add_action( 'update_option', array( $this, 'jumpstart_has_updated_module_option' ) ); |
623
|
|
|
|
624
|
|
|
// Identity Crisis AJAX callback function |
625
|
|
|
add_action( 'wp_ajax_jetpack_resolve_identity_crisis', array( $this, 'resolve_identity_crisis_ajax_callback' ) ); |
626
|
|
|
|
627
|
|
|
// JITM AJAX callback function |
628
|
|
|
add_action( 'wp_ajax_jitm_ajax', array( $this, 'jetpack_jitm_ajax_callback' ) ); |
629
|
|
|
|
630
|
|
|
add_action( 'wp_ajax_jetpack_admin_ajax', array( $this, 'jetpack_admin_ajax_callback' ) ); |
631
|
|
|
add_action( 'wp_ajax_jetpack_admin_ajax_refresh', array( $this, 'jetpack_admin_ajax_refresh_data' ) ); |
632
|
|
|
|
633
|
|
|
add_action( 'wp_loaded', array( $this, 'register_assets' ) ); |
634
|
|
|
add_action( 'wp_enqueue_scripts', array( $this, 'devicepx' ) ); |
635
|
|
|
add_action( 'customize_controls_enqueue_scripts', array( $this, 'devicepx' ) ); |
636
|
|
|
add_action( 'admin_enqueue_scripts', array( $this, 'devicepx' ) ); |
637
|
|
|
|
638
|
|
|
add_action( 'jetpack_activate_module', array( $this, 'activate_module_actions' ) ); |
639
|
|
|
|
640
|
|
|
add_action( 'plugins_loaded', array( $this, 'extra_oembed_providers' ), 100 ); |
641
|
|
|
|
642
|
|
|
add_action( 'jetpack_notices', array( $this, 'show_development_mode_notice' ) ); |
643
|
|
|
|
644
|
|
|
/** |
645
|
|
|
* These actions run checks to load additional files. |
646
|
|
|
* They check for external files or plugins, so they need to run as late as possible. |
647
|
|
|
*/ |
648
|
|
|
add_action( 'wp_head', array( $this, 'check_open_graph' ), 1 ); |
649
|
|
|
add_action( 'plugins_loaded', array( $this, 'check_twitter_tags' ), 999 ); |
650
|
|
|
add_action( 'plugins_loaded', array( $this, 'check_rest_api_compat' ), 1000 ); |
651
|
|
|
|
652
|
|
|
add_filter( 'plugins_url', array( 'Jetpack', 'maybe_min_asset' ), 1, 3 ); |
653
|
|
|
add_filter( 'style_loader_tag', array( 'Jetpack', 'maybe_inline_style' ), 10, 2 ); |
654
|
|
|
|
655
|
|
|
add_filter( 'map_meta_cap', array( $this, 'jetpack_custom_caps' ), 1, 4 ); |
656
|
|
|
|
657
|
|
|
add_filter( 'jetpack_get_default_modules', array( $this, 'filter_default_modules' ) ); |
658
|
|
|
add_filter( 'jetpack_get_default_modules', array( $this, 'handle_deprecated_modules' ), 99 ); |
659
|
|
|
|
660
|
|
|
// A filter to control all just in time messages |
661
|
|
|
add_filter( 'jetpack_just_in_time_msgs', '__return_true' ); |
662
|
|
|
|
663
|
|
|
/** |
664
|
|
|
* This is the hack to concatinate all css files into one. |
665
|
|
|
* For description and reasoning see the implode_frontend_css method |
666
|
|
|
* |
667
|
|
|
* Super late priority so we catch all the registered styles |
668
|
|
|
*/ |
669
|
|
|
if( !is_admin() ) { |
670
|
|
|
add_action( 'wp_print_styles', array( $this, 'implode_frontend_css' ), -1 ); // Run first |
671
|
|
|
add_action( 'wp_print_footer_scripts', array( $this, 'implode_frontend_css' ), -1 ); // Run first to trigger before `print_late_styles` |
672
|
|
|
} |
673
|
|
|
|
674
|
|
|
// Sync Core Icon: Detect changes in Core's Site Icon and make it syncable. |
675
|
|
|
add_action( 'add_option_site_icon', array( $this, 'jetpack_sync_core_icon' ) ); |
676
|
|
|
add_action( 'update_option_site_icon', array( $this, 'jetpack_sync_core_icon' ) ); |
677
|
|
|
add_action( 'delete_option_site_icon', array( $this, 'jetpack_sync_core_icon' ) ); |
678
|
|
|
add_action( 'jetpack_heartbeat', array( $this, 'jetpack_sync_core_icon' ) ); |
679
|
|
|
|
680
|
|
|
} |
681
|
|
|
|
682
|
|
|
/* |
683
|
|
|
* Make sure any site icon added to core can get |
684
|
|
|
* synced back to dotcom, so we can display it there. |
685
|
|
|
*/ |
686
|
|
|
function jetpack_sync_core_icon() { |
687
|
|
|
if ( function_exists( 'get_site_icon_url' ) ) { |
688
|
|
|
$url = get_site_icon_url(); |
689
|
|
|
} else { |
690
|
|
|
return; |
691
|
|
|
} |
692
|
|
|
|
693
|
|
|
require_once( JETPACK__PLUGIN_DIR . 'modules/site-icon/site-icon-functions.php' ); |
694
|
|
|
// If there's a core icon, maybe update the option. If not, fall back to Jetpack's. |
695
|
|
|
if ( ! empty( $url ) && $url !== jetpack_site_icon_url() ) { |
696
|
|
|
// This is the option that is synced with dotcom |
697
|
|
|
Jetpack_Options::update_option( 'site_icon_url', $url ); |
698
|
|
|
} else if ( empty( $url ) && did_action( 'delete_option_site_icon' ) ) { |
699
|
|
|
Jetpack_Options::delete_option( 'site_icon_url' ); |
700
|
|
|
} |
701
|
|
|
} |
702
|
|
|
|
703
|
|
|
function jetpack_admin_ajax_callback() { |
704
|
|
|
// Check for nonce |
705
|
|
View Code Duplication |
if ( ! isset( $_REQUEST['adminNonce'] ) || ! wp_verify_nonce( $_REQUEST['adminNonce'], 'jetpack-admin-nonce' ) || ! current_user_can( 'jetpack_manage_modules' ) ) { |
706
|
|
|
wp_die( 'permissions check failed' ); |
707
|
|
|
} |
708
|
|
|
|
709
|
|
|
if ( isset( $_REQUEST['toggleModule'] ) && 'nux-toggle-module' == $_REQUEST['toggleModule'] ) { |
710
|
|
|
$slug = $_REQUEST['thisModuleSlug']; |
711
|
|
|
|
712
|
|
|
if ( ! in_array( $slug, Jetpack::get_available_modules() ) ) { |
713
|
|
|
wp_die( 'That is not a Jetpack module slug' ); |
714
|
|
|
} |
715
|
|
|
|
716
|
|
|
if ( Jetpack::is_module_active( $slug ) ) { |
717
|
|
|
Jetpack::deactivate_module( $slug ); |
718
|
|
|
} else { |
719
|
|
|
Jetpack::activate_module( $slug, false, false ); |
720
|
|
|
} |
721
|
|
|
|
722
|
|
|
$modules = Jetpack_Admin::init()->get_modules(); |
723
|
|
|
echo json_encode( $modules[ $slug ] ); |
724
|
|
|
|
725
|
|
|
exit; |
|
|
|
|
726
|
|
|
} |
727
|
|
|
|
728
|
|
|
wp_die(); |
729
|
|
|
} |
730
|
|
|
|
731
|
|
|
/* |
732
|
|
|
* Sometimes we need to refresh the data, |
733
|
|
|
* especially if the page is visited via a 'history' |
734
|
|
|
* event like back/forward |
735
|
|
|
*/ |
736
|
|
|
function jetpack_admin_ajax_refresh_data() { |
737
|
|
|
// Check for nonce |
738
|
|
View Code Duplication |
if ( ! isset( $_REQUEST['adminNonce'] ) || ! wp_verify_nonce( $_REQUEST['adminNonce'], 'jetpack-admin-nonce' ) ) { |
739
|
|
|
wp_die( 'permissions check failed' ); |
740
|
|
|
} |
741
|
|
|
|
742
|
|
|
if ( isset( $_REQUEST['refreshData'] ) && 'refresh' == $_REQUEST['refreshData'] ) { |
743
|
|
|
$modules = Jetpack_Admin::init()->get_modules(); |
744
|
|
|
echo json_encode( $modules ); |
745
|
|
|
exit; |
|
|
|
|
746
|
|
|
} |
747
|
|
|
|
748
|
|
|
wp_die(); |
749
|
|
|
} |
750
|
|
|
|
751
|
|
|
/** |
752
|
|
|
* The callback for the Jump Start ajax requests. |
753
|
|
|
*/ |
754
|
|
|
function jetpack_jumpstart_ajax_callback() { |
755
|
|
|
// Check for nonce |
756
|
|
|
if ( ! isset( $_REQUEST['jumpstartNonce'] ) || ! wp_verify_nonce( $_REQUEST['jumpstartNonce'], 'jetpack-jumpstart-nonce' ) ) |
757
|
|
|
wp_die( 'permissions check failed' ); |
758
|
|
|
|
759
|
|
|
if ( isset( $_REQUEST['jumpStartActivate'] ) && 'jump-start-activate' == $_REQUEST['jumpStartActivate'] ) { |
760
|
|
|
// Update the jumpstart option |
761
|
|
|
if ( 'new_connection' === Jetpack_Options::get_option( 'jumpstart' ) ) { |
762
|
|
|
Jetpack_Options::update_option( 'jumpstart', 'jumpstart_activated' ); |
763
|
|
|
} |
764
|
|
|
|
765
|
|
|
// Loops through the requested "Jump Start" modules, and activates them. |
766
|
|
|
// Custom 'no_message' state, so that no message will be shown on reload. |
767
|
|
|
$modules = $_REQUEST['jumpstartModSlug']; |
768
|
|
|
$module_slugs = array(); |
769
|
|
|
foreach( $modules as $module => $value ) { |
770
|
|
|
$module_slugs[] = $value['module_slug']; |
771
|
|
|
} |
772
|
|
|
|
773
|
|
|
// Check for possible conflicting plugins |
774
|
|
|
$module_slugs_filtered = $this->filter_default_modules( $module_slugs ); |
775
|
|
|
|
776
|
|
|
foreach ( $module_slugs_filtered as $module_slug ) { |
777
|
|
|
Jetpack::log( 'activate', $module_slug ); |
778
|
|
|
Jetpack::activate_module( $module_slug, false, false ); |
779
|
|
|
Jetpack::state( 'message', 'no_message' ); |
780
|
|
|
} |
781
|
|
|
|
782
|
|
|
// Set the default sharing buttons and set to display on posts if none have been set. |
783
|
|
|
$sharing_services = get_option( 'sharing-services' ); |
784
|
|
|
$sharing_options = get_option( 'sharing-options' ); |
785
|
|
|
if ( empty( $sharing_services['visible'] ) ) { |
786
|
|
|
// Default buttons to set |
787
|
|
|
$visible = array( |
788
|
|
|
'twitter', |
789
|
|
|
'facebook', |
790
|
|
|
'google-plus-1', |
791
|
|
|
); |
792
|
|
|
$hidden = array(); |
793
|
|
|
|
794
|
|
|
// Set some sharing settings |
795
|
|
|
$sharing = new Sharing_Service(); |
796
|
|
|
$sharing_options['global'] = array( |
797
|
|
|
'button_style' => 'icon', |
798
|
|
|
'sharing_label' => $sharing->default_sharing_label, |
799
|
|
|
'open_links' => 'same', |
800
|
|
|
'show' => array( 'post' ), |
801
|
|
|
'custom' => isset( $sharing_options['global']['custom'] ) ? $sharing_options['global']['custom'] : array() |
802
|
|
|
); |
803
|
|
|
|
804
|
|
|
update_option( 'sharing-options', $sharing_options ); |
805
|
|
|
|
806
|
|
|
// Send a success response so that we can display an error message. |
807
|
|
|
$success = update_option( 'sharing-services', array( 'visible' => $visible, 'hidden' => $hidden ) ); |
808
|
|
|
echo json_encode( $success ); |
809
|
|
|
exit; |
|
|
|
|
810
|
|
|
} |
811
|
|
|
|
812
|
|
|
} elseif ( isset( $_REQUEST['disableJumpStart'] ) && true == $_REQUEST['disableJumpStart'] ) { |
813
|
|
|
// If dismissed, flag the jumpstart option as such. |
814
|
|
|
// Send a success response so that we can display an error message. |
815
|
|
|
if ( 'new_connection' === Jetpack_Options::get_option( 'jumpstart' ) ) { |
816
|
|
|
$success = Jetpack_Options::update_option( 'jumpstart', 'jumpstart_dismissed' ); |
817
|
|
|
echo json_encode( $success ); |
818
|
|
|
exit; |
|
|
|
|
819
|
|
|
} |
820
|
|
|
|
821
|
|
|
} elseif ( isset( $_REQUEST['jumpStartDeactivate'] ) && 'jump-start-deactivate' == $_REQUEST['jumpStartDeactivate'] ) { |
822
|
|
|
|
823
|
|
|
// FOR TESTING ONLY |
824
|
|
|
// @todo remove |
|
|
|
|
825
|
|
|
$modules = (array) $_REQUEST['jumpstartModSlug']; |
826
|
|
|
foreach( $modules as $module => $value ) { |
827
|
|
|
if ( !in_array( $value['module_slug'], Jetpack::get_default_modules() ) ) { |
828
|
|
|
Jetpack::log( 'deactivate', $value['module_slug'] ); |
829
|
|
|
Jetpack::deactivate_module( $value['module_slug'] ); |
830
|
|
|
Jetpack::state( 'message', 'no_message' ); |
831
|
|
|
} else { |
832
|
|
|
Jetpack::log( 'activate', $value['module_slug'] ); |
833
|
|
|
Jetpack::activate_module( $value['module_slug'], false, false ); |
834
|
|
|
Jetpack::state( 'message', 'no_message' ); |
835
|
|
|
} |
836
|
|
|
} |
837
|
|
|
|
838
|
|
|
Jetpack_Options::update_option( 'jumpstart', 'new_connection' ); |
839
|
|
|
echo "reload the page"; |
840
|
|
|
} |
841
|
|
|
|
842
|
|
|
wp_die(); |
843
|
|
|
} |
844
|
|
|
|
845
|
|
|
/** |
846
|
|
|
* The callback for the JITM ajax requests. |
847
|
|
|
*/ |
848
|
|
|
function jetpack_jitm_ajax_callback() { |
849
|
|
|
// Check for nonce |
850
|
|
|
if ( ! isset( $_REQUEST['jitmNonce'] ) || ! wp_verify_nonce( $_REQUEST['jitmNonce'], 'jetpack-jitm-nonce' ) ) { |
851
|
|
|
wp_die( 'Module activation failed due to lack of appropriate permissions' ); |
852
|
|
|
} |
853
|
|
|
if ( isset( $_REQUEST['jitmActionToTake'] ) && 'activate' == $_REQUEST['jitmActionToTake'] ) { |
854
|
|
|
$module_slug = $_REQUEST['jitmModule']; |
855
|
|
|
Jetpack::log( 'activate', $module_slug ); |
856
|
|
|
Jetpack::activate_module( $module_slug, false, false ); |
857
|
|
|
Jetpack::state( 'message', 'no_message' ); |
858
|
|
|
|
859
|
|
|
//A Jetpack module is being activated through a JITM, track it |
860
|
|
|
$this->stat( 'jitm', $module_slug.'-activated-' . JETPACK__VERSION ); |
861
|
|
|
$this->do_stats( 'server_side' ); |
862
|
|
|
|
863
|
|
|
wp_send_json_success(); |
864
|
|
|
} |
865
|
|
|
if ( isset( $_REQUEST['jitmActionToTake'] ) && 'dismiss' == $_REQUEST['jitmActionToTake'] ) { |
866
|
|
|
// get the hide_jitm options array |
867
|
|
|
$jetpack_hide_jitm = Jetpack_Options::get_option( 'hide_jitm' ); |
868
|
|
|
$module_slug = $_REQUEST['jitmModule']; |
869
|
|
|
|
870
|
|
|
if( ! $jetpack_hide_jitm ) { |
871
|
|
|
$jetpack_hide_jitm = array( |
872
|
|
|
$module_slug => 'hide' |
873
|
|
|
); |
874
|
|
|
} else { |
875
|
|
|
$jetpack_hide_jitm[$module_slug] = 'hide'; |
876
|
|
|
} |
877
|
|
|
|
878
|
|
|
Jetpack_Options::update_option( 'hide_jitm', $jetpack_hide_jitm ); |
879
|
|
|
|
880
|
|
|
//jitm is being dismissed forever, track it |
881
|
|
|
$this->stat( 'jitm', $module_slug.'-dismissed-' . JETPACK__VERSION ); |
882
|
|
|
$this->do_stats( 'server_side' ); |
883
|
|
|
|
884
|
|
|
wp_send_json_success(); |
885
|
|
|
} |
886
|
|
View Code Duplication |
if ( isset( $_REQUEST['jitmActionToTake'] ) && 'launch' == $_REQUEST['jitmActionToTake'] ) { |
887
|
|
|
$module_slug = $_REQUEST['jitmModule']; |
888
|
|
|
|
889
|
|
|
// User went to WordPress.com, track this |
890
|
|
|
$this->stat( 'jitm', $module_slug.'-wordpress-tools-' . JETPACK__VERSION ); |
891
|
|
|
$this->do_stats( 'server_side' ); |
892
|
|
|
|
893
|
|
|
wp_send_json_success(); |
894
|
|
|
} |
895
|
|
View Code Duplication |
if ( isset( $_REQUEST['jitmActionToTake'] ) && 'viewed' == $_REQUEST['jitmActionToTake'] ) { |
896
|
|
|
$track = $_REQUEST['jitmModule']; |
897
|
|
|
|
898
|
|
|
// User is viewing JITM, track it. |
899
|
|
|
$this->stat( 'jitm', $track . '-viewed-' . JETPACK__VERSION ); |
900
|
|
|
$this->do_stats( 'server_side' ); |
901
|
|
|
|
902
|
|
|
wp_send_json_success(); |
903
|
|
|
} |
904
|
|
|
} |
905
|
|
|
|
906
|
|
|
/** |
907
|
|
|
* If there are any stats that need to be pushed, but haven't been, push them now. |
908
|
|
|
*/ |
909
|
|
|
function __destruct() { |
910
|
|
|
if ( ! empty( $this->stats ) ) { |
911
|
|
|
$this->do_stats( 'server_side' ); |
912
|
|
|
} |
913
|
|
|
} |
914
|
|
|
|
915
|
|
|
function jetpack_custom_caps( $caps, $cap, $user_id, $args ) { |
|
|
|
|
916
|
|
|
switch( $cap ) { |
917
|
|
|
case 'jetpack_connect' : |
918
|
|
|
case 'jetpack_reconnect' : |
|
|
|
|
919
|
|
|
if ( Jetpack::is_development_mode() ) { |
920
|
|
|
$caps = array( 'do_not_allow' ); |
921
|
|
|
break; |
922
|
|
|
} |
923
|
|
|
/** |
924
|
|
|
* Pass through. If it's not development mode, these should match disconnect. |
925
|
|
|
* Let users disconnect if it's development mode, just in case things glitch. |
926
|
|
|
*/ |
927
|
|
|
case 'jetpack_disconnect' : |
928
|
|
|
/** |
929
|
|
|
* In multisite, can individual site admins manage their own connection? |
930
|
|
|
* |
931
|
|
|
* Ideally, this should be extracted out to a separate filter in the Jetpack_Network class. |
932
|
|
|
*/ |
933
|
|
|
if ( is_multisite() && ! is_super_admin() && is_plugin_active_for_network( 'jetpack/jetpack.php' ) ) { |
934
|
|
|
if ( ! Jetpack_Network::init()->get_option( 'sub-site-connection-override' ) ) { |
935
|
|
|
/** |
936
|
|
|
* We need to update the option name -- it's terribly unclear which |
937
|
|
|
* direction the override goes. |
938
|
|
|
* |
939
|
|
|
* @todo: Update the option name to `sub-sites-can-manage-own-connections` |
|
|
|
|
940
|
|
|
*/ |
941
|
|
|
$caps = array( 'do_not_allow' ); |
942
|
|
|
break; |
943
|
|
|
} |
944
|
|
|
} |
945
|
|
|
|
946
|
|
|
$caps = array( 'manage_options' ); |
947
|
|
|
break; |
948
|
|
|
case 'jetpack_manage_modules' : |
949
|
|
|
case 'jetpack_activate_modules' : |
950
|
|
|
case 'jetpack_deactivate_modules' : |
951
|
|
|
$caps = array( 'manage_options' ); |
952
|
|
|
break; |
953
|
|
|
case 'jetpack_configure_modules' : |
954
|
|
|
$caps = array( 'manage_options' ); |
955
|
|
|
break; |
956
|
|
|
case 'jetpack_network_admin_page': |
957
|
|
|
case 'jetpack_network_settings_page': |
958
|
|
|
$caps = array( 'manage_network_plugins' ); |
959
|
|
|
break; |
960
|
|
|
case 'jetpack_network_sites_page': |
961
|
|
|
$caps = array( 'manage_sites' ); |
962
|
|
|
break; |
963
|
|
|
case 'jetpack_admin_page' : |
|
|
|
|
964
|
|
|
if ( Jetpack::is_development_mode() ) { |
965
|
|
|
$caps = array( 'manage_options' ); |
966
|
|
|
break; |
967
|
|
|
} |
968
|
|
|
|
969
|
|
|
// Don't ever show to subscribers, but allow access to the page if they're trying to unlink. |
970
|
|
|
if ( ! current_user_can( 'edit_posts' ) ) { |
971
|
|
|
if ( isset( $_GET['redirect'] ) && 'sub-unlink' == $_GET['redirect'] ) { |
972
|
|
|
// We need this in order to unlink the user. |
973
|
|
|
$this->admin_page_load(); |
974
|
|
|
} |
975
|
|
|
if ( ! wp_verify_nonce( 'jetpack-unlink' ) ) { |
976
|
|
|
$caps = array( 'do_not_allow' ); |
977
|
|
|
break; |
978
|
|
|
} |
979
|
|
|
} |
980
|
|
|
|
981
|
|
|
if ( ! self::is_active() && ! current_user_can( 'jetpack_connect' ) ) { |
982
|
|
|
$caps = array( 'do_not_allow' ); |
983
|
|
|
break; |
984
|
|
|
} |
985
|
|
|
/** |
986
|
|
|
* Pass through. If it's not development mode, these should match the admin page. |
987
|
|
|
* Let users disconnect if it's development mode, just in case things glitch. |
988
|
|
|
*/ |
989
|
|
|
case 'jetpack_connect_user' : |
990
|
|
|
if ( Jetpack::is_development_mode() ) { |
991
|
|
|
$caps = array( 'do_not_allow' ); |
992
|
|
|
break; |
993
|
|
|
} |
994
|
|
|
$caps = array( 'read' ); |
995
|
|
|
break; |
996
|
|
|
} |
997
|
|
|
return $caps; |
998
|
|
|
} |
999
|
|
|
|
1000
|
|
|
function require_jetpack_authentication() { |
1001
|
|
|
// Don't let anyone authenticate |
1002
|
|
|
$_COOKIE = array(); |
1003
|
|
|
remove_all_filters( 'authenticate' ); |
1004
|
|
|
|
1005
|
|
|
/** |
1006
|
|
|
* For the moment, remove Limit Login Attempts if its xmlrpc for Jetpack. |
1007
|
|
|
* If Limit Login Attempts is installed as a mu-plugin, it can occasionally |
1008
|
|
|
* generate false-positives. |
1009
|
|
|
*/ |
1010
|
|
|
remove_filter( 'wp_login_failed', 'limit_login_failed' ); |
1011
|
|
|
|
1012
|
|
|
if ( Jetpack::is_active() ) { |
1013
|
|
|
// Allow Jetpack authentication |
1014
|
|
|
add_filter( 'authenticate', array( $this, 'authenticate_jetpack' ), 10, 3 ); |
1015
|
|
|
} |
1016
|
|
|
} |
1017
|
|
|
|
1018
|
|
|
/** |
1019
|
|
|
* Load language files |
1020
|
|
|
*/ |
1021
|
|
|
public static function plugin_textdomain() { |
1022
|
|
|
// Note to self, the third argument must not be hardcoded, to account for relocated folders. |
1023
|
|
|
load_plugin_textdomain( 'jetpack', false, dirname( plugin_basename( JETPACK__PLUGIN_FILE ) ) . '/languages/' ); |
1024
|
|
|
} |
1025
|
|
|
|
1026
|
|
|
/** |
1027
|
|
|
* Register assets for use in various modules and the Jetpack admin page. |
1028
|
|
|
* |
1029
|
|
|
* @uses wp_script_is, wp_register_script, plugins_url |
1030
|
|
|
* @action wp_loaded |
1031
|
|
|
* @return null |
1032
|
|
|
*/ |
1033
|
|
|
public function register_assets() { |
1034
|
|
|
if ( ! wp_script_is( 'spin', 'registered' ) ) { |
1035
|
|
|
wp_register_script( 'spin', plugins_url( '_inc/spin.js', JETPACK__PLUGIN_FILE ), false, '1.3' ); |
1036
|
|
|
} |
1037
|
|
|
|
1038
|
|
|
if ( ! wp_script_is( 'jquery.spin', 'registered' ) ) { |
1039
|
|
|
wp_register_script( 'jquery.spin', plugins_url( '_inc/jquery.spin.js', JETPACK__PLUGIN_FILE ) , array( 'jquery', 'spin' ), '1.3' ); |
1040
|
|
|
} |
1041
|
|
|
|
1042
|
|
View Code Duplication |
if ( ! wp_script_is( 'jetpack-gallery-settings', 'registered' ) ) { |
1043
|
|
|
wp_register_script( 'jetpack-gallery-settings', plugins_url( '_inc/gallery-settings.js', JETPACK__PLUGIN_FILE ), array( 'media-views' ), '20121225' ); |
1044
|
|
|
} |
1045
|
|
|
|
1046
|
|
|
/** |
1047
|
|
|
* As jetpack_register_genericons is by default fired off a hook, |
1048
|
|
|
* the hook may have already fired by this point. |
1049
|
|
|
* So, let's just trigger it manually. |
1050
|
|
|
*/ |
1051
|
|
|
require_once( JETPACK__PLUGIN_DIR . '_inc/genericons.php' ); |
1052
|
|
|
jetpack_register_genericons(); |
1053
|
|
|
|
1054
|
|
View Code Duplication |
if ( ! wp_style_is( 'jetpack-icons', 'registered' ) ) |
1055
|
|
|
wp_register_style( 'jetpack-icons', plugins_url( 'css/jetpack-icons.min.css', JETPACK__PLUGIN_FILE ), false, JETPACK__VERSION ); |
1056
|
|
|
} |
1057
|
|
|
|
1058
|
|
|
/** |
1059
|
|
|
* Device Pixels support |
1060
|
|
|
* This improves the resolution of gravatars and wordpress.com uploads on hi-res and zoomed browsers. |
1061
|
|
|
*/ |
1062
|
|
|
function devicepx() { |
1063
|
|
|
if ( Jetpack::is_active() ) { |
1064
|
|
|
wp_enqueue_script( 'devicepx', set_url_scheme( 'http://s0.wp.com/wp-content/js/devicepx-jetpack.js' ), array(), gmdate( 'oW' ), true ); |
1065
|
|
|
} |
1066
|
|
|
} |
1067
|
|
|
|
1068
|
|
|
/* |
1069
|
|
|
* Returns the location of Jetpack's lib directory. This filter is applied |
1070
|
|
|
* in require_lib(). |
1071
|
|
|
* |
1072
|
|
|
* @filter require_lib_dir |
1073
|
|
|
*/ |
1074
|
|
|
function require_lib_dir() { |
1075
|
|
|
return JETPACK__PLUGIN_DIR . '_inc/lib'; |
1076
|
|
|
} |
1077
|
|
|
|
1078
|
|
|
/** |
1079
|
|
|
* Return the network_site_url so that .com knows what network this site is a part of. |
1080
|
|
|
* @param bool $option |
1081
|
|
|
* @return string |
1082
|
|
|
*/ |
1083
|
|
|
public function jetpack_main_network_site_option( $option ) { |
|
|
|
|
1084
|
|
|
return network_site_url(); |
1085
|
|
|
} |
1086
|
|
|
/** |
1087
|
|
|
* Network Name. |
1088
|
|
|
*/ |
1089
|
|
|
static function network_name( $option = null ) { |
|
|
|
|
1090
|
|
|
global $current_site; |
1091
|
|
|
return $current_site->site_name; |
1092
|
|
|
} |
1093
|
|
|
/** |
1094
|
|
|
* Does the network allow new user and site registrations. |
1095
|
|
|
* @return string |
1096
|
|
|
*/ |
1097
|
|
|
static function network_allow_new_registrations( $option = null ) { |
|
|
|
|
1098
|
|
|
return ( in_array( get_site_option( 'registration' ), array('none', 'user', 'blog', 'all' ) ) ? get_site_option( 'registration') : 'none' ); |
1099
|
|
|
} |
1100
|
|
|
/** |
1101
|
|
|
* Does the network allow admins to add new users. |
1102
|
|
|
* @return boolian |
1103
|
|
|
*/ |
1104
|
|
|
static function network_add_new_users( $option = null ) { |
|
|
|
|
1105
|
|
|
return (bool) get_site_option( 'add_new_users' ); |
1106
|
|
|
} |
1107
|
|
|
/** |
1108
|
|
|
* File upload psace left per site in MB. |
1109
|
|
|
* -1 means NO LIMIT. |
1110
|
|
|
* @return number |
1111
|
|
|
*/ |
1112
|
|
|
static function network_site_upload_space( $option = null ) { |
|
|
|
|
1113
|
|
|
// value in MB |
1114
|
|
|
return ( get_site_option( 'upload_space_check_disabled' ) ? -1 : get_space_allowed() ); |
1115
|
|
|
} |
1116
|
|
|
|
1117
|
|
|
/** |
1118
|
|
|
* Network allowed file types. |
1119
|
|
|
* @return string |
1120
|
|
|
*/ |
1121
|
|
|
static function network_upload_file_types( $option = null ) { |
|
|
|
|
1122
|
|
|
return get_site_option( 'upload_filetypes', 'jpg jpeg png gif' ); |
1123
|
|
|
} |
1124
|
|
|
|
1125
|
|
|
/** |
1126
|
|
|
* Maximum file upload size set by the network. |
1127
|
|
|
* @return number |
1128
|
|
|
*/ |
1129
|
|
|
static function network_max_upload_file_size( $option = null ) { |
|
|
|
|
1130
|
|
|
// value in KB |
1131
|
|
|
return get_site_option( 'fileupload_maxk', 300 ); |
1132
|
|
|
} |
1133
|
|
|
|
1134
|
|
|
/** |
1135
|
|
|
* Lets us know if a site allows admins to manage the network. |
1136
|
|
|
* @return array |
1137
|
|
|
*/ |
1138
|
|
|
static function network_enable_administration_menus( $option = null ) { |
|
|
|
|
1139
|
|
|
return get_site_option( 'menu_items' ); |
1140
|
|
|
} |
1141
|
|
|
|
1142
|
|
|
/** |
1143
|
|
|
* Return whether we are dealing with a multi network setup or not. |
1144
|
|
|
* The reason we are type casting this is because we want to avoid the situation where |
1145
|
|
|
* the result is false since when is_main_network_option return false it cases |
1146
|
|
|
* the rest the get_option( 'jetpack_is_multi_network' ); to return the value that is set in the |
1147
|
|
|
* database which could be set to anything as opposed to what this function returns. |
1148
|
|
|
* @param bool $option |
1149
|
|
|
* |
1150
|
|
|
* @return boolean |
1151
|
|
|
*/ |
1152
|
|
|
public function is_main_network_option( $option ) { |
|
|
|
|
1153
|
|
|
// return '1' or '' |
1154
|
|
|
return (string) (bool) Jetpack::is_multi_network(); |
1155
|
|
|
} |
1156
|
|
|
|
1157
|
|
|
/** |
1158
|
|
|
* Return true if we are with multi-site or multi-network false if we are dealing with single site. |
1159
|
|
|
* |
1160
|
|
|
* @param string $option |
1161
|
|
|
* @return boolean |
1162
|
|
|
*/ |
1163
|
|
|
public function is_multisite( $option ) { |
|
|
|
|
1164
|
|
|
return (string) (bool) is_multisite(); |
1165
|
|
|
} |
1166
|
|
|
|
1167
|
|
|
/** |
1168
|
|
|
* Implemented since there is no core is multi network function |
1169
|
|
|
* Right now there is no way to tell if we which network is the dominant network on the system |
1170
|
|
|
* |
1171
|
|
|
* @since 3.3 |
1172
|
|
|
* @return boolean |
1173
|
|
|
*/ |
1174
|
|
|
public static function is_multi_network() { |
1175
|
|
|
global $wpdb; |
1176
|
|
|
|
1177
|
|
|
// if we don't have a multi site setup no need to do any more |
1178
|
|
|
if ( ! is_multisite() ) { |
1179
|
|
|
return false; |
1180
|
|
|
} |
1181
|
|
|
|
1182
|
|
|
$num_sites = $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->site}" ); |
1183
|
|
|
if ( $num_sites > 1 ) { |
1184
|
|
|
return true; |
1185
|
|
|
} else { |
1186
|
|
|
return false; |
1187
|
|
|
} |
1188
|
|
|
} |
1189
|
|
|
|
1190
|
|
|
/** |
1191
|
|
|
* Trigger an update to the main_network_site when we update the siteurl of a site. |
1192
|
|
|
* @return null |
1193
|
|
|
*/ |
1194
|
|
|
function update_jetpack_main_network_site_option() { |
1195
|
|
|
// do_action( 'add_option_$option', '$option', '$value-of-the-option' ); |
1196
|
|
|
/** |
1197
|
|
|
* Fires when the site URL is updated. |
1198
|
|
|
* Determines if the site is the main site of a Mulitiste network. |
1199
|
|
|
* |
1200
|
|
|
* @since 3.3.0 |
1201
|
|
|
* |
1202
|
|
|
* @param string jetpack_main_network_site. |
1203
|
|
|
* @param string network_site_url() Site URL for the "main" site of the current Multisite network. |
1204
|
|
|
*/ |
1205
|
|
|
do_action( 'add_option_jetpack_main_network_site', 'jetpack_main_network_site', network_site_url() ); |
1206
|
|
|
/** |
1207
|
|
|
* Fires when the site URL is updated. |
1208
|
|
|
* Determines if the is part of a multi network. |
1209
|
|
|
* |
1210
|
|
|
* @since 3.3.0 |
1211
|
|
|
* |
1212
|
|
|
* @param string jetpack_is_main_network. |
1213
|
|
|
* @param bool Jetpack::is_multi_network() Is the site part of a multi network. |
1214
|
|
|
*/ |
1215
|
|
|
do_action( 'add_option_jetpack_is_main_network', 'jetpack_is_main_network', (string) (bool) Jetpack::is_multi_network() ); |
1216
|
|
|
/** |
1217
|
|
|
* Fires when the site URL is updated. |
1218
|
|
|
* Determines if the site is part of a multisite network. |
1219
|
|
|
* |
1220
|
|
|
* @since 3.4.0 |
1221
|
|
|
* |
1222
|
|
|
* @param string jetpack_is_multi_site. |
1223
|
|
|
* @param bool is_multisite() Is the site part of a mutlisite network. |
1224
|
|
|
*/ |
1225
|
|
|
do_action( 'add_option_jetpack_is_multi_site', 'jetpack_is_multi_site', (string) (bool) is_multisite() ); |
1226
|
|
|
} |
1227
|
|
|
/** |
1228
|
|
|
* Triggered after a user updates the network settings via Network Settings Admin Page |
1229
|
|
|
* |
1230
|
|
|
*/ |
1231
|
|
|
function update_jetpack_network_settings() { |
1232
|
|
|
// Only sync this info for the main network site. |
1233
|
|
|
do_action( 'add_option_jetpack_network_name', 'jetpack_network_name', Jetpack::network_name() ); |
1234
|
|
|
do_action( 'add_option_jetpack_network_allow_new_registrations', 'jetpack_network_allow_new_registrations', Jetpack::network_allow_new_registrations() ); |
1235
|
|
|
do_action( 'add_option_jetpack_network_add_new_users', 'jetpack_network_add_new_users', Jetpack::network_add_new_users() ); |
1236
|
|
|
do_action( 'add_option_jetpack_network_site_upload_space', 'jetpack_network_site_upload_space', Jetpack::network_site_upload_space() ); |
1237
|
|
|
do_action( 'add_option_jetpack_network_upload_file_types', 'jetpack_network_upload_file_types', Jetpack::network_upload_file_types() ); |
1238
|
|
|
do_action( 'add_option_jetpack_network_enable_administration_menus', 'jetpack_network_enable_administration_menus', Jetpack::network_enable_administration_menus() ); |
1239
|
|
|
|
1240
|
|
|
} |
1241
|
|
|
|
1242
|
|
|
/** |
1243
|
|
|
* Get back if the current site is single user site. |
1244
|
|
|
* |
1245
|
|
|
* @return bool |
1246
|
|
|
*/ |
1247
|
|
|
public static function is_single_user_site() { |
1248
|
|
|
|
1249
|
|
|
$user_query = new WP_User_Query( array( |
1250
|
|
|
'blog_id' => get_current_blog_id(), |
1251
|
|
|
'fields' => 'ID', |
1252
|
|
|
'number' => 2 |
1253
|
|
|
) ); |
1254
|
|
|
return 1 === (int) $user_query->get_total(); |
1255
|
|
|
} |
1256
|
|
|
|
1257
|
|
|
/** |
1258
|
|
|
* Returns true if the site has file write access false otherwise. |
1259
|
|
|
* @return string ( '1' | '0' ) |
1260
|
|
|
**/ |
1261
|
|
|
public static function file_system_write_access() { |
1262
|
|
|
if ( ! function_exists( 'get_filesystem_method' ) ) { |
1263
|
|
|
require_once( ABSPATH . 'wp-admin/includes/file.php' ); |
1264
|
|
|
} |
1265
|
|
|
|
1266
|
|
|
require_once( ABSPATH . 'wp-admin/includes/template.php' ); |
1267
|
|
|
|
1268
|
|
|
$filesystem_method = get_filesystem_method(); |
1269
|
|
|
if ( $filesystem_method === 'direct' ) { |
1270
|
|
|
return 1; |
1271
|
|
|
} |
1272
|
|
|
|
1273
|
|
|
ob_start(); |
1274
|
|
|
$filesystem_credentials_are_stored = request_filesystem_credentials( self_admin_url() ); |
1275
|
|
|
ob_end_clean(); |
1276
|
|
|
if ( $filesystem_credentials_are_stored ) { |
1277
|
|
|
return 1; |
1278
|
|
|
} |
1279
|
|
|
return 0; |
1280
|
|
|
} |
1281
|
|
|
|
1282
|
|
|
/** |
1283
|
|
|
* Finds out if a site is using a version control system. |
1284
|
|
|
* @return string ( '1' | '0' ) |
1285
|
|
|
**/ |
1286
|
|
|
public static function is_version_controlled() { |
1287
|
|
|
|
1288
|
|
|
if ( !class_exists( 'WP_Automatic_Updater' ) ) { |
1289
|
|
|
require_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' ); |
1290
|
|
|
} |
1291
|
|
|
$updater = new WP_Automatic_Updater(); |
1292
|
|
|
$is_version_controlled = strval( $updater->is_vcs_checkout( $context = ABSPATH ) ); |
1293
|
|
|
// transients should not be empty |
1294
|
|
|
if ( empty( $is_version_controlled ) ) { |
1295
|
|
|
$is_version_controlled = '0'; |
1296
|
|
|
} |
1297
|
|
|
return $is_version_controlled; |
1298
|
|
|
} |
1299
|
|
|
|
1300
|
|
|
/** |
1301
|
|
|
* Determines whether the current theme supports featured images or not. |
1302
|
|
|
* @return string ( '1' | '0' ) |
1303
|
|
|
*/ |
1304
|
|
|
public static function featured_images_enabled() { |
1305
|
|
|
return current_theme_supports( 'post-thumbnails' ) ? '1' : '0'; |
1306
|
|
|
} |
1307
|
|
|
|
1308
|
|
|
/* |
1309
|
|
|
* Sync back wp_version |
1310
|
|
|
*/ |
1311
|
|
|
public static function get_wp_version() { |
1312
|
|
|
global $wp_version; |
1313
|
|
|
return $wp_version; |
1314
|
|
|
} |
1315
|
|
|
|
1316
|
|
|
/** |
1317
|
|
|
* Keeps wp_version in sync with .com when WordPress core updates |
1318
|
|
|
**/ |
1319
|
|
|
public static function update_get_wp_version( $update, $meta_data ) { |
1320
|
|
|
if ( 'update' === $meta_data['action'] && 'core' === $meta_data['type'] ) { |
1321
|
|
|
/** This action is documented in wp-includes/option.php */ |
1322
|
|
|
/** |
1323
|
|
|
* This triggers the sync for the jetpack version |
1324
|
|
|
* See Jetpack_Sync options method for more info. |
1325
|
|
|
*/ |
1326
|
|
|
do_action( 'add_option_jetpack_wp_version', 'jetpack_wp_version', (string) Jetpack::get_wp_version() ); |
1327
|
|
|
} |
1328
|
|
|
} |
1329
|
|
|
|
1330
|
|
|
/** |
1331
|
|
|
* Triggers a sync of update counts and update details |
1332
|
|
|
*/ |
1333
|
|
|
function sync_update_data() { |
1334
|
|
|
// Anytime WordPress saves update data, we'll want to sync update data |
1335
|
|
|
add_action( 'set_site_transient_update_plugins', array( 'Jetpack', 'refresh_update_data' ) ); |
1336
|
|
|
add_action( 'set_site_transient_update_themes', array( 'Jetpack', 'refresh_update_data' ) ); |
1337
|
|
|
add_action( 'set_site_transient_update_core', array( 'Jetpack', 'refresh_update_data' ) ); |
1338
|
|
|
// Anytime a connection to jetpack is made, sync the update data |
1339
|
|
|
add_action( 'jetpack_site_registered', array( 'Jetpack', 'refresh_update_data' ) ); |
1340
|
|
|
// Anytime the Jetpack Version changes, sync the the update data |
1341
|
|
|
add_action( 'updating_jetpack_version', array( 'Jetpack', 'refresh_update_data' ) ); |
1342
|
|
|
|
1343
|
|
|
if ( current_user_can( 'update_core' ) && current_user_can( 'update_plugins' ) && current_user_can( 'update_themes' ) ) { |
1344
|
|
|
$this->sync->mock_option( 'updates', array( 'Jetpack', 'get_updates' ) ); |
1345
|
|
|
} |
1346
|
|
|
|
1347
|
|
|
$this->sync->mock_option( 'update_details', array( 'Jetpack', 'get_update_details' ) ); |
1348
|
|
|
} |
1349
|
|
|
|
1350
|
|
|
/** |
1351
|
|
|
* Triggers a sync of information specific to the current theme. |
1352
|
|
|
*/ |
1353
|
|
|
function sync_theme_data() { |
1354
|
|
|
add_action( 'switch_theme', array( 'Jetpack', 'refresh_theme_data' ) ); |
1355
|
|
|
$this->sync->mock_option( 'featured_images_enabled', array( 'Jetpack', 'featured_images_enabled' ) ); |
1356
|
|
|
} |
1357
|
|
|
|
1358
|
|
|
/** |
1359
|
|
|
* jetpack_updates is saved in the following schema: |
1360
|
|
|
* |
1361
|
|
|
* array ( |
1362
|
|
|
* 'plugins' => (int) Number of plugin updates available. |
1363
|
|
|
* 'themes' => (int) Number of theme updates available. |
1364
|
|
|
* 'wordpress' => (int) Number of WordPress core updates available. |
1365
|
|
|
* 'translations' => (int) Number of translation updates available. |
1366
|
|
|
* 'total' => (int) Total of all available updates. |
1367
|
|
|
* 'wp_update_version' => (string) The latest available version of WordPress, only present if a WordPress update is needed. |
1368
|
|
|
* ) |
1369
|
|
|
* @return array |
1370
|
|
|
*/ |
1371
|
|
|
public static function get_updates() { |
1372
|
|
|
$update_data = wp_get_update_data(); |
1373
|
|
|
|
1374
|
|
|
// Stores the individual update counts as well as the total count. |
1375
|
|
|
if ( isset( $update_data['counts'] ) ) { |
1376
|
|
|
$updates = $update_data['counts']; |
1377
|
|
|
} |
1378
|
|
|
|
1379
|
|
|
// If we need to update WordPress core, let's find the latest version number. |
1380
|
|
View Code Duplication |
if ( ! empty( $updates['wordpress'] ) ) { |
1381
|
|
|
$cur = get_preferred_from_update_core(); |
1382
|
|
|
if ( isset( $cur->response ) && 'upgrade' === $cur->response ) { |
1383
|
|
|
$updates['wp_update_version'] = $cur->current; |
1384
|
|
|
} |
1385
|
|
|
} |
1386
|
|
|
return isset( $updates ) ? $updates : array(); |
1387
|
|
|
} |
1388
|
|
|
|
1389
|
|
|
public static function get_update_details() { |
1390
|
|
|
$update_details = array( |
1391
|
|
|
'update_core' => get_site_transient( 'update_core' ), |
1392
|
|
|
'update_plugins' => get_site_transient( 'update_plugins' ), |
1393
|
|
|
'update_themes' => get_site_transient( 'update_themes' ), |
1394
|
|
|
); |
1395
|
|
|
return $update_details; |
1396
|
|
|
} |
1397
|
|
|
|
1398
|
|
|
public static function refresh_update_data() { |
1399
|
|
|
if ( current_user_can( 'update_core' ) && current_user_can( 'update_plugins' ) && current_user_can( 'update_themes' ) ) { |
1400
|
|
|
/** |
1401
|
|
|
* Fires whenever the amount of updates needed for a site changes. |
1402
|
|
|
* Syncs an array that includes the number of theme, plugin, and core updates available, as well as the latest core version available. |
1403
|
|
|
* |
1404
|
|
|
* @since 3.7.0 |
1405
|
|
|
* |
1406
|
|
|
* @param string jetpack_updates |
1407
|
|
|
* @param array Update counts calculated by Jetpack::get_updates |
1408
|
|
|
*/ |
1409
|
|
|
do_action( 'add_option_jetpack_updates', 'jetpack_updates', Jetpack::get_updates() ); |
1410
|
|
|
} |
1411
|
|
|
/** |
1412
|
|
|
* Fires whenever the amount of updates needed for a site changes. |
1413
|
|
|
* Syncs an array of core, theme, and plugin data, and which of each is out of date |
1414
|
|
|
* |
1415
|
|
|
* @since 3.7.0 |
1416
|
|
|
* |
1417
|
|
|
* @param string jetpack_update_details |
1418
|
|
|
* @param array Update details calculated by Jetpack::get_update_details |
1419
|
|
|
*/ |
1420
|
|
|
do_action( 'add_option_jetpack_update_details', 'jetpack_update_details', Jetpack::get_update_details() ); |
1421
|
|
|
} |
1422
|
|
|
|
1423
|
|
|
public static function refresh_theme_data() { |
1424
|
|
|
/** |
1425
|
|
|
* Fires whenever a theme change is made. |
1426
|
|
|
* |
1427
|
|
|
* @since 3.8.1 |
1428
|
|
|
* |
1429
|
|
|
* @param string featured_images_enabled |
1430
|
|
|
* @param boolean Whether featured images are enabled or not |
1431
|
|
|
*/ |
1432
|
|
|
do_action( 'add_option_jetpack_featured_images_enabled', 'jetpack_featured_images_enabled', Jetpack::featured_images_enabled() ); |
1433
|
|
|
} |
1434
|
|
|
|
1435
|
|
|
/** |
1436
|
|
|
* Invalides the transient as well as triggers the update of the mock option. |
1437
|
|
|
* |
1438
|
|
|
* @return null |
1439
|
|
|
*/ |
1440
|
|
|
function is_single_user_site_invalidate() { |
1441
|
|
|
/** |
1442
|
|
|
* Fires when a user is added or removed from a site. |
1443
|
|
|
* Determines if the site is a single user site. |
1444
|
|
|
* |
1445
|
|
|
* @since 3.4.0 |
1446
|
|
|
* |
1447
|
|
|
* @param string jetpack_single_user_site. |
1448
|
|
|
* @param bool Jetpack::is_single_user_site() Is the current site a single user site. |
1449
|
|
|
*/ |
1450
|
|
|
do_action( 'update_option_jetpack_single_user_site', 'jetpack_single_user_site', (bool) Jetpack::is_single_user_site() ); |
1451
|
|
|
} |
1452
|
|
|
|
1453
|
|
|
/** |
1454
|
|
|
* Is Jetpack active? |
1455
|
|
|
*/ |
1456
|
|
|
public static function is_active() { |
1457
|
|
|
return (bool) Jetpack_Data::get_access_token( JETPACK_MASTER_USER ); |
1458
|
|
|
} |
1459
|
|
|
|
1460
|
|
|
/** |
1461
|
|
|
* Is Jetpack in development (offline) mode? |
1462
|
|
|
*/ |
1463
|
|
|
public static function is_development_mode() { |
1464
|
|
|
$development_mode = false; |
1465
|
|
|
|
1466
|
|
|
if ( defined( 'JETPACK_DEV_DEBUG' ) ) { |
1467
|
|
|
$development_mode = JETPACK_DEV_DEBUG; |
1468
|
|
|
} |
1469
|
|
|
|
1470
|
|
|
elseif ( site_url() && false === strpos( site_url(), '.' ) ) { |
1471
|
|
|
$development_mode = true; |
1472
|
|
|
} |
1473
|
|
|
/** |
1474
|
|
|
* Filters Jetpack's development mode. |
1475
|
|
|
* |
1476
|
|
|
* @see http://jetpack.me/support/development-mode/ |
1477
|
|
|
* |
1478
|
|
|
* @since 2.2.1 |
1479
|
|
|
* |
1480
|
|
|
* @param bool $development_mode Is Jetpack's development mode active. |
1481
|
|
|
*/ |
1482
|
|
|
return apply_filters( 'jetpack_development_mode', $development_mode ); |
1483
|
|
|
} |
1484
|
|
|
|
1485
|
|
|
/** |
1486
|
|
|
* Get Jetpack development mode notice text and notice class. |
1487
|
|
|
* |
1488
|
|
|
* Mirrors the checks made in Jetpack::is_development_mode |
1489
|
|
|
* |
1490
|
|
|
*/ |
1491
|
|
|
public static function show_development_mode_notice() { |
1492
|
|
|
if ( Jetpack::is_development_mode() ) { |
1493
|
|
|
if ( defined( 'JETPACK_DEV_DEBUG' ) && JETPACK_DEV_DEBUG ) { |
1494
|
|
|
$notice = sprintf( |
1495
|
|
|
/* translators: %s is a URL */ |
1496
|
|
|
__( 'In <a href="%s" target="_blank">Development Mode</a>, via the JETPACK_DEV_DEBUG constant being defined in wp-config.php or elsewhere.', 'jetpack' ), |
1497
|
|
|
'http://jetpack.me/support/development-mode/' |
1498
|
|
|
); |
1499
|
|
|
} elseif ( site_url() && false === strpos( site_url(), '.' ) ) { |
1500
|
|
|
$notice = sprintf( |
1501
|
|
|
/* translators: %s is a URL */ |
1502
|
|
|
__( 'In <a href="%s" target="_blank">Development Mode</a>, via site URL lacking a dot (e.g. http://localhost).', 'jetpack' ), |
1503
|
|
|
'http://jetpack.me/support/development-mode/' |
1504
|
|
|
); |
1505
|
|
|
} else { |
1506
|
|
|
$notice = sprintf( |
1507
|
|
|
/* translators: %s is a URL */ |
1508
|
|
|
__( 'In <a href="%s" target="_blank">Development Mode</a>, via the jetpack_development_mode filter.', 'jetpack' ), |
1509
|
|
|
'http://jetpack.me/support/development-mode/' |
1510
|
|
|
); |
1511
|
|
|
} |
1512
|
|
|
|
1513
|
|
|
echo '<div class="updated" style="border-color: #f0821e;"><p>' . $notice . '</p></div>'; |
1514
|
|
|
} |
1515
|
|
|
|
1516
|
|
|
// Throw up a notice if using a development version and as for feedback. |
1517
|
|
|
if ( Jetpack::is_development_version() ) { |
1518
|
|
|
/* translators: %s is a URL */ |
1519
|
|
|
$notice = sprintf( __( 'You are currently running a development version of Jetpack. <a href="%s" target="_blank">Submit your feedback</a>', 'jetpack' ), 'https://jetpack.me/contact-support/beta-group/' ); |
1520
|
|
|
|
1521
|
|
|
echo '<div class="updated" style="border-color: #f0821e;"><p>' . $notice . '</p></div>'; |
1522
|
|
|
} |
1523
|
|
|
} |
1524
|
|
|
|
1525
|
|
|
/** |
1526
|
|
|
* Whether Jetpack's version maps to a public release, or a development version. |
1527
|
|
|
*/ |
1528
|
|
|
public static function is_development_version() { |
1529
|
|
|
return ! preg_match( '/^\d+(\.\d+)+$/', JETPACK__VERSION ); |
1530
|
|
|
} |
1531
|
|
|
|
1532
|
|
|
/** |
1533
|
|
|
* Is a given user (or the current user if none is specified) linked to a WordPress.com user? |
1534
|
|
|
*/ |
1535
|
|
|
public static function is_user_connected( $user_id = false ) { |
1536
|
|
|
$user_id = false === $user_id ? get_current_user_id() : absint( $user_id ); |
1537
|
|
|
if ( ! $user_id ) { |
1538
|
|
|
return false; |
1539
|
|
|
} |
1540
|
|
|
return (bool) Jetpack_Data::get_access_token( $user_id ); |
1541
|
|
|
} |
1542
|
|
|
|
1543
|
|
|
/** |
1544
|
|
|
* Get the wpcom user data of the current|specified connected user. |
1545
|
|
|
*/ |
1546
|
|
View Code Duplication |
public static function get_connected_user_data( $user_id = null ) { |
1547
|
|
|
if ( ! $user_id ) { |
1548
|
|
|
$user_id = get_current_user_id(); |
1549
|
|
|
} |
1550
|
|
|
Jetpack::load_xml_rpc_client(); |
1551
|
|
|
$xml = new Jetpack_IXR_Client( array( |
1552
|
|
|
'user_id' => $user_id, |
1553
|
|
|
) ); |
1554
|
|
|
$xml->query( 'wpcom.getUser' ); |
1555
|
|
|
if ( ! $xml->isError() ) { |
1556
|
|
|
return $xml->getResponse(); |
1557
|
|
|
} |
1558
|
|
|
return false; |
1559
|
|
|
} |
1560
|
|
|
|
1561
|
|
|
/** |
1562
|
|
|
* Get the wpcom email of the current|specified connected user. |
1563
|
|
|
*/ |
1564
|
|
View Code Duplication |
public static function get_connected_user_email( $user_id = null ) { |
1565
|
|
|
if ( ! $user_id ) { |
1566
|
|
|
$user_id = get_current_user_id(); |
1567
|
|
|
} |
1568
|
|
|
Jetpack::load_xml_rpc_client(); |
1569
|
|
|
$xml = new Jetpack_IXR_Client( array( |
1570
|
|
|
'user_id' => $user_id, |
1571
|
|
|
) ); |
1572
|
|
|
$xml->query( 'wpcom.getUserEmail' ); |
1573
|
|
|
if ( ! $xml->isError() ) { |
1574
|
|
|
return $xml->getResponse(); |
1575
|
|
|
} |
1576
|
|
|
return false; |
1577
|
|
|
} |
1578
|
|
|
|
1579
|
|
|
/** |
1580
|
|
|
* Get the wpcom email of the master user. |
1581
|
|
|
*/ |
1582
|
|
|
public static function get_master_user_email() { |
1583
|
|
|
$master_user_id = Jetpack_Options::get_option( 'master_user' ); |
1584
|
|
|
if ( $master_user_id ) { |
1585
|
|
|
return self::get_connected_user_email( $master_user_id ); |
1586
|
|
|
} |
1587
|
|
|
return ''; |
1588
|
|
|
} |
1589
|
|
|
|
1590
|
|
|
function current_user_is_connection_owner() { |
1591
|
|
|
$user_token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER ); |
1592
|
|
|
return $user_token && is_object( $user_token ) && isset( $user_token->external_user_id ) && get_current_user_id() === $user_token->external_user_id; |
1593
|
|
|
} |
1594
|
|
|
|
1595
|
|
|
/** |
1596
|
|
|
* Add any extra oEmbed providers that we know about and use on wpcom for feature parity. |
1597
|
|
|
*/ |
1598
|
|
|
function extra_oembed_providers() { |
1599
|
|
|
// Cloudup: https://dev.cloudup.com/#oembed |
1600
|
|
|
wp_oembed_add_provider( 'https://cloudup.com/*' , 'https://cloudup.com/oembed' ); |
1601
|
|
|
wp_oembed_add_provider( 'https://me.sh/*', 'https://me.sh/oembed?format=json' ); |
1602
|
|
|
wp_oembed_add_provider( '#https?://(www\.)?gfycat\.com/.*#i', 'https://api.gfycat.com/v1/oembed', true ); |
1603
|
|
|
wp_oembed_add_provider( '#https?://[^.]+\.(wistia\.com|wi\.st)/(medias|embed)/.*#', 'https://fast.wistia.com/oembed', true ); |
1604
|
|
|
} |
1605
|
|
|
|
1606
|
|
|
/** |
1607
|
|
|
* Synchronize connected user role changes |
1608
|
|
|
*/ |
1609
|
|
|
function user_role_change( $user_id ) { |
1610
|
|
|
if ( Jetpack::is_active() && Jetpack::is_user_connected( $user_id ) ) { |
1611
|
|
|
$current_user_id = get_current_user_id(); |
1612
|
|
|
wp_set_current_user( $user_id ); |
1613
|
|
|
$role = $this->translate_current_user_to_role(); |
1614
|
|
|
$signed_role = $this->sign_role( $role ); |
1615
|
|
|
wp_set_current_user( $current_user_id ); |
1616
|
|
|
|
1617
|
|
|
$master_token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER ); |
1618
|
|
|
$master_user_id = absint( $master_token->external_user_id ); |
1619
|
|
|
|
1620
|
|
|
if ( ! $master_user_id ) |
1621
|
|
|
return; // this shouldn't happen |
1622
|
|
|
|
1623
|
|
|
Jetpack::xmlrpc_async_call( 'jetpack.updateRole', $user_id, $signed_role ); |
1624
|
|
|
//@todo retry on failure |
|
|
|
|
1625
|
|
|
|
1626
|
|
|
//try to choose a new master if we're demoting the current one |
1627
|
|
|
if ( $user_id == $master_user_id && 'administrator' != $role ) { |
1628
|
|
|
$query = new WP_User_Query( |
1629
|
|
|
array( |
1630
|
|
|
'fields' => array( 'id' ), |
1631
|
|
|
'role' => 'administrator', |
1632
|
|
|
'orderby' => 'id', |
1633
|
|
|
'exclude' => array( $master_user_id ), |
1634
|
|
|
) |
1635
|
|
|
); |
1636
|
|
|
$new_master = false; |
1637
|
|
|
foreach ( $query->results as $result ) { |
1638
|
|
|
$uid = absint( $result->id ); |
1639
|
|
|
if ( $uid && Jetpack::is_user_connected( $uid ) ) { |
1640
|
|
|
$new_master = $uid; |
1641
|
|
|
break; |
1642
|
|
|
} |
1643
|
|
|
} |
1644
|
|
|
|
1645
|
|
|
if ( $new_master ) { |
1646
|
|
|
Jetpack_Options::update_option( 'master_user', $new_master ); |
1647
|
|
|
} |
1648
|
|
|
// else disconnect..? |
1649
|
|
|
} |
1650
|
|
|
} |
1651
|
|
|
} |
1652
|
|
|
|
1653
|
|
|
/** |
1654
|
|
|
* Loads the currently active modules. |
1655
|
|
|
*/ |
1656
|
|
|
public static function load_modules() { |
1657
|
|
|
if ( ! self::is_active() && !self::is_development_mode() ) { |
1658
|
|
|
if ( ! is_multisite() || ! get_site_option( 'jetpack_protect_active' ) ) { |
1659
|
|
|
return; |
1660
|
|
|
} |
1661
|
|
|
} |
1662
|
|
|
|
1663
|
|
|
$version = Jetpack_Options::get_option( 'version' ); |
1664
|
|
View Code Duplication |
if ( ! $version ) { |
1665
|
|
|
$version = $old_version = JETPACK__VERSION . ':' . time(); |
1666
|
|
|
/** This action is documented in class.jetpack.php */ |
1667
|
|
|
do_action( 'updating_jetpack_version', $version, false ); |
1668
|
|
|
Jetpack_Options::update_options( compact( 'version', 'old_version' ) ); |
1669
|
|
|
} |
1670
|
|
|
list( $version ) = explode( ':', $version ); |
1671
|
|
|
|
1672
|
|
|
$modules = array_filter( Jetpack::get_active_modules(), array( 'Jetpack', 'is_module' ) ); |
1673
|
|
|
|
1674
|
|
|
$modules_data = array(); |
1675
|
|
|
|
1676
|
|
|
// Don't load modules that have had "Major" changes since the stored version until they have been deactivated/reactivated through the lint check. |
1677
|
|
|
if ( version_compare( $version, JETPACK__VERSION, '<' ) ) { |
1678
|
|
|
$updated_modules = array(); |
1679
|
|
|
foreach ( $modules as $module ) { |
1680
|
|
|
$modules_data[ $module ] = Jetpack::get_module( $module ); |
1681
|
|
|
if ( ! isset( $modules_data[ $module ]['changed'] ) ) { |
1682
|
|
|
continue; |
1683
|
|
|
} |
1684
|
|
|
|
1685
|
|
|
if ( version_compare( $modules_data[ $module ]['changed'], $version, '<=' ) ) { |
1686
|
|
|
continue; |
1687
|
|
|
} |
1688
|
|
|
|
1689
|
|
|
$updated_modules[] = $module; |
1690
|
|
|
} |
1691
|
|
|
|
1692
|
|
|
$modules = array_diff( $modules, $updated_modules ); |
1693
|
|
|
} |
1694
|
|
|
|
1695
|
|
|
$is_development_mode = Jetpack::is_development_mode(); |
1696
|
|
|
|
1697
|
|
|
foreach ( $modules as $module ) { |
1698
|
|
|
// If we're in dev mode, disable modules requiring a connection |
1699
|
|
|
if ( $is_development_mode ) { |
1700
|
|
|
// Prime the pump if we need to |
1701
|
|
|
if ( empty( $modules_data[ $module ] ) ) { |
1702
|
|
|
$modules_data[ $module ] = Jetpack::get_module( $module ); |
1703
|
|
|
} |
1704
|
|
|
// If the module requires a connection, but we're in local mode, don't include it. |
1705
|
|
|
if ( $modules_data[ $module ]['requires_connection'] ) { |
1706
|
|
|
continue; |
1707
|
|
|
} |
1708
|
|
|
} |
1709
|
|
|
|
1710
|
|
|
if ( did_action( 'jetpack_module_loaded_' . $module ) ) { |
1711
|
|
|
continue; |
1712
|
|
|
} |
1713
|
|
|
|
1714
|
|
|
require Jetpack::get_module_path( $module ); |
1715
|
|
|
/** |
1716
|
|
|
* Fires when a specific module is loaded. |
1717
|
|
|
* The dynamic part of the hook, $module, is the module slug. |
1718
|
|
|
* |
1719
|
|
|
* @since 1.1.0 |
1720
|
|
|
*/ |
1721
|
|
|
do_action( 'jetpack_module_loaded_' . $module ); |
1722
|
|
|
} |
1723
|
|
|
|
1724
|
|
|
/** |
1725
|
|
|
* Fires when all the modules are loaded. |
1726
|
|
|
* |
1727
|
|
|
* @since 1.1.0 |
1728
|
|
|
*/ |
1729
|
|
|
do_action( 'jetpack_modules_loaded' ); |
1730
|
|
|
|
1731
|
|
|
// Load module-specific code that is needed even when a module isn't active. Loaded here because code contained therein may need actions such as setup_theme. |
1732
|
|
|
if ( Jetpack::is_active() || Jetpack::is_development_mode() ) |
1733
|
|
|
require_once( JETPACK__PLUGIN_DIR . 'modules/module-extras.php' ); |
1734
|
|
|
} |
1735
|
|
|
|
1736
|
|
|
/** |
1737
|
|
|
* Check if Jetpack's REST API compat file should be included |
1738
|
|
|
* @action plugins_loaded |
1739
|
|
|
* @return null |
1740
|
|
|
*/ |
1741
|
|
|
public function check_rest_api_compat() { |
1742
|
|
|
/** |
1743
|
|
|
* Filters the list of REST API compat files to be included. |
1744
|
|
|
* |
1745
|
|
|
* @since 2.2.5 |
1746
|
|
|
* |
1747
|
|
|
* @param array $args Array of REST API compat files to include. |
1748
|
|
|
*/ |
1749
|
|
|
$_jetpack_rest_api_compat_includes = apply_filters( 'jetpack_rest_api_compat', array() ); |
1750
|
|
|
|
1751
|
|
|
if ( function_exists( 'bbpress' ) ) |
1752
|
|
|
$_jetpack_rest_api_compat_includes[] = JETPACK__PLUGIN_DIR . 'class.jetpack-bbpress-json-api-compat.php'; |
1753
|
|
|
|
1754
|
|
|
foreach ( $_jetpack_rest_api_compat_includes as $_jetpack_rest_api_compat_include ) |
1755
|
|
|
require_once $_jetpack_rest_api_compat_include; |
1756
|
|
|
} |
1757
|
|
|
|
1758
|
|
|
/** |
1759
|
|
|
* Gets all plugins currently active in values, regardless of whether they're |
1760
|
|
|
* traditionally activated or network activated. |
1761
|
|
|
* |
1762
|
|
|
* @todo Store the result in core's object cache maybe? |
|
|
|
|
1763
|
|
|
*/ |
1764
|
|
|
public static function get_active_plugins() { |
1765
|
|
|
$active_plugins = (array) get_option( 'active_plugins', array() ); |
1766
|
|
|
|
1767
|
|
|
if ( is_multisite() ) { |
1768
|
|
|
// Due to legacy code, active_sitewide_plugins stores them in the keys, |
1769
|
|
|
// whereas active_plugins stores them in the values. |
1770
|
|
|
$network_plugins = array_keys( get_site_option( 'active_sitewide_plugins', array() ) ); |
1771
|
|
|
if ( $network_plugins ) { |
|
|
|
|
1772
|
|
|
$active_plugins = array_merge( $active_plugins, $network_plugins ); |
1773
|
|
|
} |
1774
|
|
|
} |
1775
|
|
|
|
1776
|
|
|
sort( $active_plugins ); |
1777
|
|
|
|
1778
|
|
|
return array_unique( $active_plugins ); |
1779
|
|
|
} |
1780
|
|
|
|
1781
|
|
|
/** |
1782
|
|
|
* Gets and parses additional plugin data to send with the heartbeat data |
1783
|
|
|
* |
1784
|
|
|
* @since 3.8.1 |
1785
|
|
|
* |
1786
|
|
|
* @return array Array of plugin data |
1787
|
|
|
*/ |
1788
|
|
|
public static function get_parsed_plugin_data() { |
1789
|
|
|
if ( ! function_exists( 'get_plugins' ) ) { |
1790
|
|
|
require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); |
1791
|
|
|
} |
1792
|
|
|
$all_plugins = get_plugins(); |
1793
|
|
|
$active_plugins = Jetpack::get_active_plugins(); |
1794
|
|
|
|
1795
|
|
|
$plugins = array(); |
1796
|
|
|
foreach ( $all_plugins as $path => $plugin_data ) { |
1797
|
|
|
$plugins[ $path ] = array( |
1798
|
|
|
'is_active' => in_array( $path, $active_plugins ), |
1799
|
|
|
'file' => $path, |
1800
|
|
|
'name' => $plugin_data['Name'], |
1801
|
|
|
'version' => $plugin_data['Version'], |
1802
|
|
|
'author' => $plugin_data['Author'], |
1803
|
|
|
); |
1804
|
|
|
} |
1805
|
|
|
|
1806
|
|
|
return $plugins; |
1807
|
|
|
} |
1808
|
|
|
|
1809
|
|
|
/** |
1810
|
|
|
* Gets and parses theme data to send with the heartbeat data |
1811
|
|
|
* |
1812
|
|
|
* @since 3.8.1 |
1813
|
|
|
* |
1814
|
|
|
* @return array Array of theme data |
1815
|
|
|
*/ |
1816
|
|
|
public static function get_parsed_theme_data() { |
1817
|
|
|
$all_themes = wp_get_themes( array( 'allowed' => true ) ); |
1818
|
|
|
$header_keys = array( 'Name', 'Author', 'Version', 'ThemeURI', 'AuthorURI', 'Status', 'Tags' ); |
1819
|
|
|
|
1820
|
|
|
$themes = array(); |
1821
|
|
|
foreach ( $all_themes as $slug => $theme_data ) { |
1822
|
|
|
$theme_headers = array(); |
1823
|
|
|
foreach ( $header_keys as $header_key ) { |
1824
|
|
|
$theme_headers[ $header_key ] = $theme_data->get( $header_key ); |
1825
|
|
|
} |
1826
|
|
|
|
1827
|
|
|
$themes[ $slug ] = array( |
1828
|
|
|
'is_active_theme' => $slug == wp_get_theme()->get_template(), |
1829
|
|
|
'slug' => $slug, |
1830
|
|
|
'theme_root' => $theme_data->get_theme_root_uri(), |
1831
|
|
|
'parent' => $theme_data->parent(), |
1832
|
|
|
'headers' => $theme_headers |
1833
|
|
|
); |
1834
|
|
|
} |
1835
|
|
|
|
1836
|
|
|
return $themes; |
1837
|
|
|
} |
1838
|
|
|
|
1839
|
|
|
/** |
1840
|
|
|
* Checks whether a specific plugin is active. |
1841
|
|
|
* |
1842
|
|
|
* We don't want to store these in a static variable, in case |
1843
|
|
|
* there are switch_to_blog() calls involved. |
1844
|
|
|
*/ |
1845
|
|
|
public static function is_plugin_active( $plugin = 'jetpack/jetpack.php' ) { |
1846
|
|
|
return in_array( $plugin, self::get_active_plugins() ); |
1847
|
|
|
} |
1848
|
|
|
|
1849
|
|
|
/** |
1850
|
|
|
* Check if Jetpack's Open Graph tags should be used. |
1851
|
|
|
* If certain plugins are active, Jetpack's og tags are suppressed. |
1852
|
|
|
* |
1853
|
|
|
* @uses Jetpack::get_active_modules, add_filter, get_option, apply_filters |
1854
|
|
|
* @action plugins_loaded |
1855
|
|
|
* @return null |
1856
|
|
|
*/ |
1857
|
|
|
public function check_open_graph() { |
1858
|
|
|
if ( in_array( 'publicize', Jetpack::get_active_modules() ) || in_array( 'sharedaddy', Jetpack::get_active_modules() ) ) { |
1859
|
|
|
add_filter( 'jetpack_enable_open_graph', '__return_true', 0 ); |
1860
|
|
|
} |
1861
|
|
|
|
1862
|
|
|
$active_plugins = self::get_active_plugins(); |
1863
|
|
|
|
1864
|
|
|
if ( ! empty( $active_plugins ) ) { |
1865
|
|
|
foreach ( $this->open_graph_conflicting_plugins as $plugin ) { |
1866
|
|
|
if ( in_array( $plugin, $active_plugins ) ) { |
1867
|
|
|
add_filter( 'jetpack_enable_open_graph', '__return_false', 99 ); |
1868
|
|
|
break; |
1869
|
|
|
} |
1870
|
|
|
} |
1871
|
|
|
} |
1872
|
|
|
|
1873
|
|
|
/** |
1874
|
|
|
* Allow the addition of Open Graph Meta Tags to all pages. |
1875
|
|
|
* |
1876
|
|
|
* @since 2.0.3 |
1877
|
|
|
* |
1878
|
|
|
* @param bool false Should Open Graph Meta tags be added. Default to false. |
1879
|
|
|
*/ |
1880
|
|
|
if ( apply_filters( 'jetpack_enable_open_graph', false ) ) { |
1881
|
|
|
require_once JETPACK__PLUGIN_DIR . 'functions.opengraph.php'; |
1882
|
|
|
} |
1883
|
|
|
} |
1884
|
|
|
|
1885
|
|
|
/** |
1886
|
|
|
* Check if Jetpack's Twitter tags should be used. |
1887
|
|
|
* If certain plugins are active, Jetpack's twitter tags are suppressed. |
1888
|
|
|
* |
1889
|
|
|
* @uses Jetpack::get_active_modules, add_filter, get_option, apply_filters |
1890
|
|
|
* @action plugins_loaded |
1891
|
|
|
* @return null |
1892
|
|
|
*/ |
1893
|
|
|
public function check_twitter_tags() { |
1894
|
|
|
|
1895
|
|
|
$active_plugins = self::get_active_plugins(); |
1896
|
|
|
|
1897
|
|
|
if ( ! empty( $active_plugins ) ) { |
1898
|
|
|
foreach ( $this->twitter_cards_conflicting_plugins as $plugin ) { |
1899
|
|
|
if ( in_array( $plugin, $active_plugins ) ) { |
1900
|
|
|
add_filter( 'jetpack_disable_twitter_cards', '__return_true', 99 ); |
1901
|
|
|
break; |
1902
|
|
|
} |
1903
|
|
|
} |
1904
|
|
|
} |
1905
|
|
|
|
1906
|
|
|
/** |
1907
|
|
|
* Allow Twitter Card Meta tags to be disabled. |
1908
|
|
|
* |
1909
|
|
|
* @since 2.6.0 |
1910
|
|
|
* |
1911
|
|
|
* @param bool true Should Twitter Card Meta tags be disabled. Default to true. |
1912
|
|
|
*/ |
1913
|
|
|
if ( apply_filters( 'jetpack_disable_twitter_cards', true ) ) { |
1914
|
|
|
require_once JETPACK__PLUGIN_DIR . 'class.jetpack-twitter-cards.php'; |
1915
|
|
|
} |
1916
|
|
|
} |
1917
|
|
|
|
1918
|
|
|
|
1919
|
|
|
|
1920
|
|
|
|
1921
|
|
|
/* |
1922
|
|
|
* |
1923
|
|
|
* Jetpack Security Reports |
1924
|
|
|
* |
1925
|
|
|
* Allowed types: login_form, backup, file_scanning, spam |
1926
|
|
|
* |
1927
|
|
|
* Args for login_form and spam: 'blocked'=>(int)(optional), 'status'=>(string)(ok, warning, error), 'message'=>(optional, disregarded if status is ok, allowed tags: a, em, strong) |
1928
|
|
|
* |
1929
|
|
|
* Args for backup and file_scanning: 'last'=>(timestamp)(optional), 'next'=>(timestamp)(optional), 'status'=>(string)(ok, warning, error), 'message'=>(optional, disregarded if status is ok, allowed tags: a, em, strong) |
1930
|
|
|
* |
1931
|
|
|
* |
1932
|
|
|
* Example code to submit a security report: |
1933
|
|
|
* |
1934
|
|
|
* function akismet_submit_jetpack_security_report() { |
1935
|
|
|
* Jetpack::submit_security_report( 'spam', __FILE__, $args = array( 'blocked' => 138284, status => 'ok' ) ); |
1936
|
|
|
* } |
1937
|
|
|
* add_action( 'jetpack_security_report', 'akismet_submit_jetpack_security_report' ); |
1938
|
|
|
* |
1939
|
|
|
*/ |
1940
|
|
|
|
1941
|
|
|
|
1942
|
|
|
/** |
1943
|
|
|
* Calls for security report submissions. |
1944
|
|
|
* |
1945
|
|
|
* @return null |
1946
|
|
|
*/ |
1947
|
|
|
public static function perform_security_reporting() { |
1948
|
|
|
$no_check_needed = get_site_transient( 'security_report_performed_recently' ); |
1949
|
|
|
|
1950
|
|
|
if ( $no_check_needed ) { |
1951
|
|
|
return; |
1952
|
|
|
} |
1953
|
|
|
|
1954
|
|
|
/** |
1955
|
|
|
* Fires before a security report is created. |
1956
|
|
|
* |
1957
|
|
|
* @since 3.4.0 |
1958
|
|
|
*/ |
1959
|
|
|
do_action( 'jetpack_security_report' ); |
1960
|
|
|
|
1961
|
|
|
Jetpack_Options::update_option( 'security_report', self::$security_report ); |
1962
|
|
|
set_site_transient( 'security_report_performed_recently', 1, 15 * MINUTE_IN_SECONDS ); |
1963
|
|
|
} |
1964
|
|
|
|
1965
|
|
|
/** |
1966
|
|
|
* Allows plugins to submit security reports. |
1967
|
|
|
* |
1968
|
|
|
* @param string $type Report type (login_form, backup, file_scanning, spam) |
1969
|
|
|
* @param string $plugin_file Plugin __FILE__, so that we can pull plugin data |
1970
|
|
|
* @param array $args See definitions above |
1971
|
|
|
*/ |
1972
|
|
|
public static function submit_security_report( $type = '', $plugin_file = '', $args = array() ) { |
1973
|
|
|
|
1974
|
|
|
if( !doing_action( 'jetpack_security_report' ) ) { |
1975
|
|
|
return new WP_Error( 'not_collecting_report', 'Not currently collecting security reports. Please use the jetpack_security_report hook.' ); |
1976
|
|
|
} |
1977
|
|
|
|
1978
|
|
|
if( !is_string( $type ) || !is_string( $plugin_file ) ) { |
1979
|
|
|
return new WP_Error( 'invalid_security_report', 'Invalid Security Report' ); |
1980
|
|
|
} |
1981
|
|
|
|
1982
|
|
|
if( !function_exists( 'get_plugin_data' ) ) { |
1983
|
|
|
include( ABSPATH . 'wp-admin/includes/plugin.php' ); |
1984
|
|
|
} |
1985
|
|
|
|
1986
|
|
|
//Get rid of any non-allowed args |
1987
|
|
|
$args = array_intersect_key( $args, array_flip( array( 'blocked', 'last', 'next', 'status', 'message' ) ) ); |
1988
|
|
|
|
1989
|
|
|
$plugin = get_plugin_data( $plugin_file ); |
1990
|
|
|
|
1991
|
|
|
if ( !$plugin['Name'] ) { |
1992
|
|
|
return new WP_Error( 'security_report_missing_plugin_name', 'Invalid Plugin File Provided' ); |
1993
|
|
|
} |
1994
|
|
|
|
1995
|
|
|
// Sanitize everything to make sure we're not syncing something wonky |
1996
|
|
|
$type = sanitize_key( $type ); |
1997
|
|
|
|
1998
|
|
|
$args['plugin'] = $plugin; |
1999
|
|
|
|
2000
|
|
|
// Cast blocked, last and next as integers. |
2001
|
|
|
// Last and next should be in unix timestamp format |
2002
|
|
|
if ( isset( $args['blocked'] ) ) { |
2003
|
|
|
$args['blocked'] = (int) $args['blocked']; |
2004
|
|
|
} |
2005
|
|
|
if ( isset( $args['last'] ) ) { |
2006
|
|
|
$args['last'] = (int) $args['last']; |
2007
|
|
|
} |
2008
|
|
|
if ( isset( $args['next'] ) ) { |
2009
|
|
|
$args['next'] = (int) $args['next']; |
2010
|
|
|
} |
2011
|
|
|
if ( !in_array( $args['status'], array( 'ok', 'warning', 'error' ) ) ) { |
2012
|
|
|
$args['status'] = 'ok'; |
2013
|
|
|
} |
2014
|
|
|
if ( isset( $args['message'] ) ) { |
2015
|
|
|
|
2016
|
|
|
if( $args['status'] == 'ok' ) { |
2017
|
|
|
unset( $args['message'] ); |
2018
|
|
|
} |
2019
|
|
|
|
2020
|
|
|
$allowed_html = array( |
2021
|
|
|
'a' => array( |
2022
|
|
|
'href' => array(), |
2023
|
|
|
'title' => array() |
2024
|
|
|
), |
2025
|
|
|
'em' => array(), |
2026
|
|
|
'strong' => array(), |
2027
|
|
|
); |
2028
|
|
|
|
2029
|
|
|
$args['message'] = wp_kses( $args['message'], $allowed_html ); |
2030
|
|
|
} |
2031
|
|
|
|
2032
|
|
|
$plugin_name = $plugin[ 'Name' ]; |
2033
|
|
|
|
2034
|
|
|
self::$security_report[ $type ][ $plugin_name ] = $args; |
2035
|
|
|
} |
2036
|
|
|
|
2037
|
|
|
/** |
2038
|
|
|
* Collects a new report if needed, then returns it. |
2039
|
|
|
*/ |
2040
|
|
|
public function get_security_report() { |
2041
|
|
|
self::perform_security_reporting(); |
2042
|
|
|
return Jetpack_Options::get_option( 'security_report' ); |
2043
|
|
|
} |
2044
|
|
|
|
2045
|
|
|
|
2046
|
|
|
/* Jetpack Options API */ |
2047
|
|
|
|
2048
|
|
|
public static function get_option_names( $type = 'compact' ) { |
2049
|
|
|
return Jetpack_Options::get_option_names( $type ); |
2050
|
|
|
} |
2051
|
|
|
|
2052
|
|
|
/** |
2053
|
|
|
* Returns the requested option. Looks in jetpack_options or jetpack_$name as appropriate. |
2054
|
|
|
* |
2055
|
|
|
* @param string $name Option name |
2056
|
|
|
* @param mixed $default (optional) |
2057
|
|
|
*/ |
2058
|
|
|
public static function get_option( $name, $default = false ) { |
2059
|
|
|
return Jetpack_Options::get_option( $name, $default ); |
2060
|
|
|
} |
2061
|
|
|
|
2062
|
|
|
/** |
2063
|
|
|
* Stores two secrets and a timestamp so WordPress.com can make a request back and verify an action |
2064
|
|
|
* Does some extra verification so urls (such as those to public-api, register, etc) can't just be crafted |
2065
|
|
|
* $name must be a registered option name. |
2066
|
|
|
*/ |
2067
|
|
|
public static function create_nonce( $name ) { |
2068
|
|
|
$secret = wp_generate_password( 32, false ) . ':' . wp_generate_password( 32, false ) . ':' . ( time() + 600 ); |
2069
|
|
|
|
2070
|
|
|
Jetpack_Options::update_option( $name, $secret ); |
2071
|
|
|
@list( $secret_1, $secret_2, $eol ) = explode( ':', Jetpack_Options::get_option( $name ) ); |
|
|
|
|
2072
|
|
|
if ( empty( $secret_1 ) || empty( $secret_2 ) || $eol < time() ) |
2073
|
|
|
return new Jetpack_Error( 'missing_secrets' ); |
2074
|
|
|
|
2075
|
|
|
return array( |
2076
|
|
|
'secret_1' => $secret_1, |
2077
|
|
|
'secret_2' => $secret_2, |
2078
|
|
|
'eol' => $eol, |
2079
|
|
|
); |
2080
|
|
|
} |
2081
|
|
|
|
2082
|
|
|
/** |
2083
|
|
|
* Updates the single given option. Updates jetpack_options or jetpack_$name as appropriate. |
2084
|
|
|
* |
2085
|
|
|
* @deprecated 3.4 use Jetpack_Options::update_option() instead. |
2086
|
|
|
* @param string $name Option name |
2087
|
|
|
* @param mixed $value Option value |
2088
|
|
|
*/ |
2089
|
|
|
public static function update_option( $name, $value ) { |
2090
|
|
|
_deprecated_function( __METHOD__, 'jetpack-3.4', 'Jetpack_Options::update_option()' ); |
2091
|
|
|
return Jetpack_Options::update_option( $name, $value ); |
2092
|
|
|
} |
2093
|
|
|
|
2094
|
|
|
/** |
2095
|
|
|
* Updates the multiple given options. Updates jetpack_options and/or jetpack_$name as appropriate. |
2096
|
|
|
* |
2097
|
|
|
* @deprecated 3.4 use Jetpack_Options::update_options() instead. |
2098
|
|
|
* @param array $array array( option name => option value, ... ) |
2099
|
|
|
*/ |
2100
|
|
|
public static function update_options( $array ) { |
2101
|
|
|
_deprecated_function( __METHOD__, 'jetpack-3.4', 'Jetpack_Options::update_options()' ); |
2102
|
|
|
return Jetpack_Options::update_options( $array ); |
2103
|
|
|
} |
2104
|
|
|
|
2105
|
|
|
/** |
2106
|
|
|
* Deletes the given option. May be passed multiple option names as an array. |
2107
|
|
|
* Updates jetpack_options and/or deletes jetpack_$name as appropriate. |
2108
|
|
|
* |
2109
|
|
|
* @deprecated 3.4 use Jetpack_Options::delete_option() instead. |
2110
|
|
|
* @param string|array $names |
2111
|
|
|
*/ |
2112
|
|
|
public static function delete_option( $names ) { |
2113
|
|
|
_deprecated_function( __METHOD__, 'jetpack-3.4', 'Jetpack_Options::delete_option()' ); |
2114
|
|
|
return Jetpack_Options::delete_option( $names ); |
2115
|
|
|
} |
2116
|
|
|
|
2117
|
|
|
/** |
2118
|
|
|
* Enters a user token into the user_tokens option |
2119
|
|
|
* |
2120
|
|
|
* @param int $user_id |
2121
|
|
|
* @param string $token |
2122
|
|
|
* return bool |
2123
|
|
|
*/ |
2124
|
|
|
public static function update_user_token( $user_id, $token, $is_master_user ) { |
2125
|
|
|
// not designed for concurrent updates |
2126
|
|
|
$user_tokens = Jetpack_Options::get_option( 'user_tokens' ); |
2127
|
|
|
if ( ! is_array( $user_tokens ) ) |
2128
|
|
|
$user_tokens = array(); |
2129
|
|
|
$user_tokens[$user_id] = $token; |
2130
|
|
|
if ( $is_master_user ) { |
2131
|
|
|
$master_user = $user_id; |
2132
|
|
|
$options = compact( 'user_tokens', 'master_user' ); |
2133
|
|
|
} else { |
2134
|
|
|
$options = compact( 'user_tokens' ); |
2135
|
|
|
} |
2136
|
|
|
return Jetpack_Options::update_options( $options ); |
2137
|
|
|
} |
2138
|
|
|
|
2139
|
|
|
/** |
2140
|
|
|
* Returns an array of all PHP files in the specified absolute path. |
2141
|
|
|
* Equivalent to glob( "$absolute_path/*.php" ). |
2142
|
|
|
* |
2143
|
|
|
* @param string $absolute_path The absolute path of the directory to search. |
2144
|
|
|
* @return array Array of absolute paths to the PHP files. |
2145
|
|
|
*/ |
2146
|
|
|
public static function glob_php( $absolute_path ) { |
2147
|
|
|
if ( function_exists( 'glob' ) ) { |
2148
|
|
|
return glob( "$absolute_path/*.php" ); |
2149
|
|
|
} |
2150
|
|
|
|
2151
|
|
|
$absolute_path = untrailingslashit( $absolute_path ); |
2152
|
|
|
$files = array(); |
2153
|
|
|
if ( ! $dir = @opendir( $absolute_path ) ) { |
2154
|
|
|
return $files; |
2155
|
|
|
} |
2156
|
|
|
|
2157
|
|
|
while ( false !== $file = readdir( $dir ) ) { |
2158
|
|
|
if ( '.' == substr( $file, 0, 1 ) || '.php' != substr( $file, -4 ) ) { |
2159
|
|
|
continue; |
2160
|
|
|
} |
2161
|
|
|
|
2162
|
|
|
$file = "$absolute_path/$file"; |
2163
|
|
|
|
2164
|
|
|
if ( ! is_file( $file ) ) { |
2165
|
|
|
continue; |
2166
|
|
|
} |
2167
|
|
|
|
2168
|
|
|
$files[] = $file; |
2169
|
|
|
} |
2170
|
|
|
|
2171
|
|
|
closedir( $dir ); |
2172
|
|
|
|
2173
|
|
|
return $files; |
2174
|
|
|
} |
2175
|
|
|
|
2176
|
|
|
public static function activate_new_modules( $redirect = false ) { |
2177
|
|
|
if ( ! Jetpack::is_active() && ! Jetpack::is_development_mode() ) { |
2178
|
|
|
return; |
2179
|
|
|
} |
2180
|
|
|
|
2181
|
|
|
$jetpack_old_version = Jetpack_Options::get_option( 'version' ); // [sic] |
2182
|
|
View Code Duplication |
if ( ! $jetpack_old_version ) { |
2183
|
|
|
$jetpack_old_version = $version = $old_version = '1.1:' . time(); |
2184
|
|
|
/** This action is documented in class.jetpack.php */ |
2185
|
|
|
do_action( 'updating_jetpack_version', $version, false ); |
2186
|
|
|
Jetpack_Options::update_options( compact( 'version', 'old_version' ) ); |
2187
|
|
|
} |
2188
|
|
|
|
2189
|
|
|
list( $jetpack_version ) = explode( ':', $jetpack_old_version ); // [sic] |
2190
|
|
|
|
2191
|
|
|
if ( version_compare( JETPACK__VERSION, $jetpack_version, '<=' ) ) { |
2192
|
|
|
return; |
2193
|
|
|
} |
2194
|
|
|
|
2195
|
|
|
$active_modules = Jetpack::get_active_modules(); |
2196
|
|
|
$reactivate_modules = array(); |
2197
|
|
|
foreach ( $active_modules as $active_module ) { |
2198
|
|
|
$module = Jetpack::get_module( $active_module ); |
2199
|
|
|
if ( ! isset( $module['changed'] ) ) { |
2200
|
|
|
continue; |
2201
|
|
|
} |
2202
|
|
|
|
2203
|
|
|
if ( version_compare( $module['changed'], $jetpack_version, '<=' ) ) { |
2204
|
|
|
continue; |
2205
|
|
|
} |
2206
|
|
|
|
2207
|
|
|
$reactivate_modules[] = $active_module; |
2208
|
|
|
Jetpack::deactivate_module( $active_module ); |
2209
|
|
|
} |
2210
|
|
|
|
2211
|
|
|
$new_version = JETPACK__VERSION . ':' . time(); |
2212
|
|
|
/** This action is documented in class.jetpack.php */ |
2213
|
|
|
do_action( 'updating_jetpack_version', $new_version, $jetpack_old_version ); |
2214
|
|
|
Jetpack_Options::update_options( |
2215
|
|
|
array( |
2216
|
|
|
'version' => $new_version, |
2217
|
|
|
'old_version' => $jetpack_old_version, |
2218
|
|
|
) |
2219
|
|
|
); |
2220
|
|
|
|
2221
|
|
|
Jetpack::state( 'message', 'modules_activated' ); |
2222
|
|
|
Jetpack::activate_default_modules( $jetpack_version, JETPACK__VERSION, $reactivate_modules ); |
|
|
|
|
2223
|
|
|
|
2224
|
|
|
if ( $redirect ) { |
2225
|
|
|
$page = 'jetpack'; // make sure we redirect to either settings or the jetpack page |
2226
|
|
|
if ( isset( $_GET['page'] ) && in_array( $_GET['page'], array( 'jetpack', 'jetpack_modules' ) ) ) { |
2227
|
|
|
$page = $_GET['page']; |
2228
|
|
|
} |
2229
|
|
|
|
2230
|
|
|
wp_safe_redirect( Jetpack::admin_url( 'page=' . $page ) ); |
2231
|
|
|
exit; |
|
|
|
|
2232
|
|
|
} |
2233
|
|
|
} |
2234
|
|
|
|
2235
|
|
|
/** |
2236
|
|
|
* List available Jetpack modules. Simply lists .php files in /modules/. |
2237
|
|
|
* Make sure to tuck away module "library" files in a sub-directory. |
2238
|
|
|
*/ |
2239
|
|
|
public static function get_available_modules( $min_version = false, $max_version = false ) { |
2240
|
|
|
static $modules = null; |
2241
|
|
|
|
2242
|
|
|
if ( ! isset( $modules ) ) { |
2243
|
|
|
$available_modules_option = Jetpack_Options::get_option( 'available_modules', array() ); |
2244
|
|
|
// Use the cache if we're on the front-end and it's available... |
2245
|
|
|
if ( ! is_admin() && ! empty( $available_modules_option[ JETPACK__VERSION ] ) ) { |
2246
|
|
|
$modules = $available_modules_option[ JETPACK__VERSION ]; |
2247
|
|
|
} else { |
2248
|
|
|
$files = Jetpack::glob_php( JETPACK__PLUGIN_DIR . 'modules' ); |
2249
|
|
|
|
2250
|
|
|
$modules = array(); |
2251
|
|
|
|
2252
|
|
|
foreach ( $files as $file ) { |
2253
|
|
|
if ( ! $headers = Jetpack::get_module( $file ) ) { |
2254
|
|
|
continue; |
2255
|
|
|
} |
2256
|
|
|
|
2257
|
|
|
$modules[ Jetpack::get_module_slug( $file ) ] = $headers['introduced']; |
2258
|
|
|
} |
2259
|
|
|
|
2260
|
|
|
Jetpack_Options::update_option( 'available_modules', array( |
2261
|
|
|
JETPACK__VERSION => $modules, |
2262
|
|
|
) ); |
2263
|
|
|
} |
2264
|
|
|
} |
2265
|
|
|
|
2266
|
|
|
/** |
2267
|
|
|
* Filters the array of modules available to be activated. |
2268
|
|
|
* |
2269
|
|
|
* @since 2.4.0 |
2270
|
|
|
* |
2271
|
|
|
* @param array $modules Array of available modules. |
2272
|
|
|
* @param string $min_version Minimum version number required to use modules. |
2273
|
|
|
* @param string $max_version Maximum version number required to use modules. |
2274
|
|
|
*/ |
2275
|
|
|
$mods = apply_filters( 'jetpack_get_available_modules', $modules, $min_version, $max_version ); |
2276
|
|
|
|
2277
|
|
|
if ( ! $min_version && ! $max_version ) { |
2278
|
|
|
return array_keys( $mods ); |
2279
|
|
|
} |
2280
|
|
|
|
2281
|
|
|
$r = array(); |
2282
|
|
|
foreach ( $mods as $slug => $introduced ) { |
2283
|
|
|
if ( $min_version && version_compare( $min_version, $introduced, '>=' ) ) { |
2284
|
|
|
continue; |
2285
|
|
|
} |
2286
|
|
|
|
2287
|
|
|
if ( $max_version && version_compare( $max_version, $introduced, '<' ) ) { |
2288
|
|
|
continue; |
2289
|
|
|
} |
2290
|
|
|
|
2291
|
|
|
$r[] = $slug; |
2292
|
|
|
} |
2293
|
|
|
|
2294
|
|
|
return $r; |
2295
|
|
|
} |
2296
|
|
|
|
2297
|
|
|
/** |
2298
|
|
|
* Default modules loaded on activation. |
2299
|
|
|
*/ |
2300
|
|
|
public static function get_default_modules( $min_version = false, $max_version = false ) { |
2301
|
|
|
$return = array(); |
2302
|
|
|
|
2303
|
|
|
foreach ( Jetpack::get_available_modules( $min_version, $max_version ) as $module ) { |
2304
|
|
|
$module_data = Jetpack::get_module( $module ); |
2305
|
|
|
|
2306
|
|
|
switch ( strtolower( $module_data['auto_activate'] ) ) { |
2307
|
|
|
case 'yes' : |
2308
|
|
|
$return[] = $module; |
2309
|
|
|
break; |
2310
|
|
|
case 'public' : |
2311
|
|
|
if ( Jetpack_Options::get_option( 'public' ) ) { |
2312
|
|
|
$return[] = $module; |
2313
|
|
|
} |
2314
|
|
|
break; |
2315
|
|
|
case 'no' : |
2316
|
|
|
default : |
|
|
|
|
2317
|
|
|
break; |
2318
|
|
|
} |
2319
|
|
|
} |
2320
|
|
|
/** |
2321
|
|
|
* Filters the array of default modules. |
2322
|
|
|
* |
2323
|
|
|
* @since 2.5.0 |
2324
|
|
|
* |
2325
|
|
|
* @param array $return Array of default modules. |
2326
|
|
|
* @param string $min_version Minimum version number required to use modules. |
2327
|
|
|
* @param string $max_version Maximum version number required to use modules. |
2328
|
|
|
*/ |
2329
|
|
|
return apply_filters( 'jetpack_get_default_modules', $return, $min_version, $max_version ); |
2330
|
|
|
} |
2331
|
|
|
|
2332
|
|
|
/** |
2333
|
|
|
* Checks activated modules during auto-activation to determine |
2334
|
|
|
* if any of those modules are being deprecated. If so, close |
2335
|
|
|
* them out, and add any replacement modules. |
2336
|
|
|
* |
2337
|
|
|
* Runs at priority 99 by default. |
2338
|
|
|
* |
2339
|
|
|
* This is run late, so that it can still activate a module if |
2340
|
|
|
* the new module is a replacement for another that the user |
2341
|
|
|
* currently has active, even if something at the normal priority |
2342
|
|
|
* would kibosh everything. |
2343
|
|
|
* |
2344
|
|
|
* @since 2.6 |
2345
|
|
|
* @uses jetpack_get_default_modules filter |
2346
|
|
|
* @param array $modules |
2347
|
|
|
* @return array |
2348
|
|
|
*/ |
2349
|
|
|
function handle_deprecated_modules( $modules ) { |
2350
|
|
|
$deprecated_modules = array( |
2351
|
|
|
'debug' => null, // Closed out and moved to ./class.jetpack-debugger.php |
2352
|
|
|
'wpcc' => 'sso', // Closed out in 2.6 -- SSO provides the same functionality. |
2353
|
|
|
'gplus-authorship' => null, // Closed out in 3.2 -- Google dropped support. |
2354
|
|
|
); |
2355
|
|
|
|
2356
|
|
|
// Don't activate SSO if they never completed activating WPCC. |
2357
|
|
|
if ( Jetpack::is_module_active( 'wpcc' ) ) { |
2358
|
|
|
$wpcc_options = Jetpack_Options::get_option( 'wpcc_options' ); |
2359
|
|
|
if ( empty( $wpcc_options ) || empty( $wpcc_options['client_id'] ) || empty( $wpcc_options['client_id'] ) ) { |
2360
|
|
|
$deprecated_modules['wpcc'] = null; |
2361
|
|
|
} |
2362
|
|
|
} |
2363
|
|
|
|
2364
|
|
|
foreach ( $deprecated_modules as $module => $replacement ) { |
2365
|
|
|
if ( Jetpack::is_module_active( $module ) ) { |
2366
|
|
|
self::deactivate_module( $module ); |
2367
|
|
|
if ( $replacement ) { |
|
|
|
|
2368
|
|
|
$modules[] = $replacement; |
2369
|
|
|
} |
2370
|
|
|
} |
2371
|
|
|
} |
2372
|
|
|
|
2373
|
|
|
return array_unique( $modules ); |
2374
|
|
|
} |
2375
|
|
|
|
2376
|
|
|
/** |
2377
|
|
|
* Checks activated plugins during auto-activation to determine |
2378
|
|
|
* if any of those plugins are in the list with a corresponding module |
2379
|
|
|
* that is not compatible with the plugin. The module will not be allowed |
2380
|
|
|
* to auto-activate. |
2381
|
|
|
* |
2382
|
|
|
* @since 2.6 |
2383
|
|
|
* @uses jetpack_get_default_modules filter |
2384
|
|
|
* @param array $modules |
2385
|
|
|
* @return array |
2386
|
|
|
*/ |
2387
|
|
|
function filter_default_modules( $modules ) { |
2388
|
|
|
|
2389
|
|
|
$active_plugins = self::get_active_plugins(); |
2390
|
|
|
|
2391
|
|
|
if ( ! empty( $active_plugins ) ) { |
2392
|
|
|
|
2393
|
|
|
// For each module we'd like to auto-activate... |
2394
|
|
|
foreach ( $modules as $key => $module ) { |
2395
|
|
|
// If there are potential conflicts for it... |
2396
|
|
|
if ( ! empty( $this->conflicting_plugins[ $module ] ) ) { |
2397
|
|
|
// For each potential conflict... |
2398
|
|
|
foreach ( $this->conflicting_plugins[ $module ] as $title => $plugin ) { |
2399
|
|
|
// If that conflicting plugin is active... |
2400
|
|
|
if ( in_array( $plugin, $active_plugins ) ) { |
2401
|
|
|
// Remove that item from being auto-activated. |
2402
|
|
|
unset( $modules[ $key ] ); |
2403
|
|
|
} |
2404
|
|
|
} |
2405
|
|
|
} |
2406
|
|
|
} |
2407
|
|
|
} |
2408
|
|
|
|
2409
|
|
|
return $modules; |
2410
|
|
|
} |
2411
|
|
|
|
2412
|
|
|
/** |
2413
|
|
|
* Extract a module's slug from its full path. |
2414
|
|
|
*/ |
2415
|
|
|
public static function get_module_slug( $file ) { |
2416
|
|
|
return str_replace( '.php', '', basename( $file ) ); |
2417
|
|
|
} |
2418
|
|
|
|
2419
|
|
|
/** |
2420
|
|
|
* Generate a module's path from its slug. |
2421
|
|
|
*/ |
2422
|
|
|
public static function get_module_path( $slug ) { |
2423
|
|
|
return JETPACK__PLUGIN_DIR . "modules/$slug.php"; |
2424
|
|
|
} |
2425
|
|
|
|
2426
|
|
|
/** |
2427
|
|
|
* Load module data from module file. Headers differ from WordPress |
2428
|
|
|
* plugin headers to avoid them being identified as standalone |
2429
|
|
|
* plugins on the WordPress plugins page. |
2430
|
|
|
*/ |
2431
|
|
|
public static function get_module( $module ) { |
2432
|
|
|
$headers = array( |
2433
|
|
|
'name' => 'Module Name', |
2434
|
|
|
'description' => 'Module Description', |
2435
|
|
|
'jumpstart_desc' => 'Jumpstart Description', |
2436
|
|
|
'sort' => 'Sort Order', |
2437
|
|
|
'recommendation_order' => 'Recommendation Order', |
2438
|
|
|
'introduced' => 'First Introduced', |
2439
|
|
|
'changed' => 'Major Changes In', |
2440
|
|
|
'deactivate' => 'Deactivate', |
2441
|
|
|
'free' => 'Free', |
2442
|
|
|
'requires_connection' => 'Requires Connection', |
2443
|
|
|
'auto_activate' => 'Auto Activate', |
2444
|
|
|
'module_tags' => 'Module Tags', |
2445
|
|
|
'feature' => 'Feature', |
2446
|
|
|
'additional_search_queries' => 'Additional Search Queries', |
2447
|
|
|
); |
2448
|
|
|
|
2449
|
|
|
$file = Jetpack::get_module_path( Jetpack::get_module_slug( $module ) ); |
2450
|
|
|
|
2451
|
|
|
$mod = Jetpack::get_file_data( $file, $headers ); |
2452
|
|
|
if ( empty( $mod['name'] ) ) { |
2453
|
|
|
return false; |
2454
|
|
|
} |
2455
|
|
|
|
2456
|
|
|
$mod['sort'] = empty( $mod['sort'] ) ? 10 : (int) $mod['sort']; |
2457
|
|
|
$mod['recommendation_order'] = empty( $mod['recommendation_order'] ) ? 20 : (int) $mod['recommendation_order']; |
2458
|
|
|
$mod['deactivate'] = empty( $mod['deactivate'] ); |
2459
|
|
|
$mod['free'] = empty( $mod['free'] ); |
2460
|
|
|
$mod['requires_connection'] = ( ! empty( $mod['requires_connection'] ) && 'No' == $mod['requires_connection'] ) ? false : true; |
2461
|
|
|
|
2462
|
|
|
if ( empty( $mod['auto_activate'] ) || ! in_array( strtolower( $mod['auto_activate'] ), array( 'yes', 'no', 'public' ) ) ) { |
2463
|
|
|
$mod['auto_activate'] = 'No'; |
2464
|
|
|
} else { |
2465
|
|
|
$mod['auto_activate'] = (string) $mod['auto_activate']; |
2466
|
|
|
} |
2467
|
|
|
|
2468
|
|
|
if ( $mod['module_tags'] ) { |
2469
|
|
|
$mod['module_tags'] = explode( ',', $mod['module_tags'] ); |
2470
|
|
|
$mod['module_tags'] = array_map( 'trim', $mod['module_tags'] ); |
2471
|
|
|
$mod['module_tags'] = array_map( array( __CLASS__, 'translate_module_tag' ), $mod['module_tags'] ); |
2472
|
|
|
} else { |
2473
|
|
|
$mod['module_tags'] = array( self::translate_module_tag( 'Other' ) ); |
2474
|
|
|
} |
2475
|
|
|
|
2476
|
|
|
if ( $mod['feature'] ) { |
2477
|
|
|
$mod['feature'] = explode( ',', $mod['feature'] ); |
2478
|
|
|
$mod['feature'] = array_map( 'trim', $mod['feature'] ); |
2479
|
|
|
} else { |
2480
|
|
|
$mod['feature'] = array( self::translate_module_tag( 'Other' ) ); |
2481
|
|
|
} |
2482
|
|
|
|
2483
|
|
|
/** |
2484
|
|
|
* Filters the feature array on a module. |
2485
|
|
|
* |
2486
|
|
|
* This filter allows you to control where each module is filtered: Recommended, |
2487
|
|
|
* Jumpstart, and the default "Other" listing. |
2488
|
|
|
* |
2489
|
|
|
* @since 3.5.0 |
2490
|
|
|
* |
2491
|
|
|
* @param array $mod['feature'] The areas to feature this module: |
2492
|
|
|
* 'Jumpstart' adds to the "Jumpstart" option to activate many modules at once. |
2493
|
|
|
* 'Recommended' shows on the main Jetpack admin screen. |
2494
|
|
|
* 'Other' should be the default if no other value is in the array. |
2495
|
|
|
* @param string $module The slug of the module, e.g. sharedaddy. |
2496
|
|
|
* @param array $mod All the currently assembled module data. |
2497
|
|
|
*/ |
2498
|
|
|
$mod['feature'] = apply_filters( 'jetpack_module_feature', $mod['feature'], $module, $mod ); |
2499
|
|
|
|
2500
|
|
|
/** |
2501
|
|
|
* Filter the returned data about a module. |
2502
|
|
|
* |
2503
|
|
|
* This filter allows overriding any info about Jetpack modules. It is dangerous, |
2504
|
|
|
* so please be careful. |
2505
|
|
|
* |
2506
|
|
|
* @since 3.6.0 |
2507
|
|
|
* |
2508
|
|
|
* @param array $mod The details of the requested module. |
2509
|
|
|
* @param string $module The slug of the module, e.g. sharedaddy |
2510
|
|
|
* @param string $file The path to the module source file. |
2511
|
|
|
*/ |
2512
|
|
|
return apply_filters( 'jetpack_get_module', $mod, $module, $file ); |
2513
|
|
|
} |
2514
|
|
|
|
2515
|
|
|
/** |
2516
|
|
|
* Like core's get_file_data implementation, but caches the result. |
2517
|
|
|
*/ |
2518
|
|
|
public static function get_file_data( $file, $headers ) { |
2519
|
|
|
//Get just the filename from $file (i.e. exclude full path) so that a consistent hash is generated |
2520
|
|
|
$file_name = basename( $file ); |
2521
|
|
|
$file_data_option = Jetpack_Options::get_option( 'file_data', array() ); |
2522
|
|
|
$key = md5( $file_name . serialize( $headers ) ); |
2523
|
|
|
$refresh_cache = is_admin() && isset( $_GET['page'] ) && 'jetpack' === substr( $_GET['page'], 0, 7 ); |
2524
|
|
|
|
2525
|
|
|
// If we don't need to refresh the cache, and already have the value, short-circuit! |
2526
|
|
|
if ( ! $refresh_cache && isset( $file_data_option[ JETPACK__VERSION ][ $key ] ) ) { |
2527
|
|
|
return $file_data_option[ JETPACK__VERSION ][ $key ]; |
2528
|
|
|
} |
2529
|
|
|
|
2530
|
|
|
$data = get_file_data( $file, $headers ); |
2531
|
|
|
|
2532
|
|
|
// Strip out any old Jetpack versions that are cluttering the option. |
2533
|
|
|
$file_data_option = array_intersect_key( (array) $file_data_option, array( JETPACK__VERSION => null ) ); |
2534
|
|
|
$file_data_option[ JETPACK__VERSION ][ $key ] = $data; |
2535
|
|
|
Jetpack_Options::update_option( 'file_data', $file_data_option ); |
2536
|
|
|
|
2537
|
|
|
return $data; |
2538
|
|
|
} |
2539
|
|
|
|
2540
|
|
|
/** |
2541
|
|
|
* Return translated module tag. |
2542
|
|
|
* |
2543
|
|
|
* @param string $tag Tag as it appears in each module heading. |
2544
|
|
|
* |
2545
|
|
|
* @return mixed |
2546
|
|
|
*/ |
2547
|
|
|
public static function translate_module_tag( $tag ) { |
2548
|
|
|
return jetpack_get_module_i18n_tag( $tag ); |
2549
|
|
|
} |
2550
|
|
|
|
2551
|
|
|
/** |
2552
|
|
|
* Return module name translation. Uses matching string created in modules/module-headings.php. |
2553
|
|
|
* |
2554
|
|
|
* @since 3.9.2 |
2555
|
|
|
* |
2556
|
|
|
* @param array $modules |
2557
|
|
|
* |
2558
|
|
|
* @return string|void |
2559
|
|
|
*/ |
2560
|
|
|
public static function get_translated_modules( $modules ) { |
2561
|
|
|
foreach ( $modules as $index => $module ) { |
2562
|
|
|
$i18n_module = jetpack_get_module_i18n( $module['module'] ); |
2563
|
|
|
if ( isset( $module['name'] ) ) { |
2564
|
|
|
$modules[ $index ]['name'] = $i18n_module['name']; |
2565
|
|
|
} |
2566
|
|
|
if ( isset( $module['description'] ) ) { |
2567
|
|
|
$modules[ $index ]['description'] = $i18n_module['description']; |
2568
|
|
|
$modules[ $index ]['short_description'] = $i18n_module['description']; |
2569
|
|
|
} |
2570
|
|
|
} |
2571
|
|
|
return $modules; |
2572
|
|
|
} |
2573
|
|
|
|
2574
|
|
|
/** |
2575
|
|
|
* Get a list of activated modules as an array of module slugs. |
2576
|
|
|
*/ |
2577
|
|
|
public static function get_active_modules() { |
2578
|
|
|
$active = Jetpack_Options::get_option( 'active_modules' ); |
2579
|
|
|
if ( ! is_array( $active ) ) |
2580
|
|
|
$active = array(); |
2581
|
|
|
if ( is_admin() && ( class_exists( 'VaultPress' ) || function_exists( 'vaultpress_contact_service' ) ) ) { |
2582
|
|
|
$active[] = 'vaultpress'; |
2583
|
|
|
} else { |
2584
|
|
|
$active = array_diff( $active, array( 'vaultpress' ) ); |
2585
|
|
|
} |
2586
|
|
|
|
2587
|
|
|
//If protect is active on the main site of a multisite, it should be active on all sites. |
2588
|
|
|
if ( ! in_array( 'protect', $active ) && is_multisite() && get_site_option( 'jetpack_protect_active' ) ) { |
2589
|
|
|
$active[] = 'protect'; |
2590
|
|
|
} |
2591
|
|
|
|
2592
|
|
|
return array_unique( $active ); |
2593
|
|
|
} |
2594
|
|
|
|
2595
|
|
|
/** |
2596
|
|
|
* Check whether or not a Jetpack module is active. |
2597
|
|
|
* |
2598
|
|
|
* @param string $module The slug of a Jetpack module. |
2599
|
|
|
* @return bool |
2600
|
|
|
* |
2601
|
|
|
* @static |
2602
|
|
|
*/ |
2603
|
|
|
public static function is_module_active( $module ) { |
2604
|
|
|
return in_array( $module, self::get_active_modules() ); |
2605
|
|
|
} |
2606
|
|
|
|
2607
|
|
|
public static function is_module( $module ) { |
2608
|
|
|
return ! empty( $module ) && ! validate_file( $module, Jetpack::get_available_modules() ); |
2609
|
|
|
} |
2610
|
|
|
|
2611
|
|
|
/** |
2612
|
|
|
* Catches PHP errors. Must be used in conjunction with output buffering. |
2613
|
|
|
* |
2614
|
|
|
* @param bool $catch True to start catching, False to stop. |
2615
|
|
|
* |
2616
|
|
|
* @static |
2617
|
|
|
*/ |
2618
|
|
|
public static function catch_errors( $catch ) { |
2619
|
|
|
static $display_errors, $error_reporting; |
2620
|
|
|
|
2621
|
|
|
if ( $catch ) { |
2622
|
|
|
$display_errors = @ini_set( 'display_errors', 1 ); |
2623
|
|
|
$error_reporting = @error_reporting( E_ALL ); |
2624
|
|
|
add_action( 'shutdown', array( 'Jetpack', 'catch_errors_on_shutdown' ), 0 ); |
2625
|
|
|
} else { |
2626
|
|
|
@ini_set( 'display_errors', $display_errors ); |
|
|
|
|
2627
|
|
|
@error_reporting( $error_reporting ); |
|
|
|
|
2628
|
|
|
remove_action( 'shutdown', array( 'Jetpack', 'catch_errors_on_shutdown' ), 0 ); |
2629
|
|
|
} |
2630
|
|
|
} |
2631
|
|
|
|
2632
|
|
|
/** |
2633
|
|
|
* Saves any generated PHP errors in ::state( 'php_errors', {errors} ) |
2634
|
|
|
*/ |
2635
|
|
|
public static function catch_errors_on_shutdown() { |
2636
|
|
|
Jetpack::state( 'php_errors', ob_get_clean() ); |
2637
|
|
|
} |
2638
|
|
|
|
2639
|
|
|
public static function activate_default_modules( $min_version = false, $max_version = false, $other_modules = array() ) { |
2640
|
|
|
$jetpack = Jetpack::init(); |
2641
|
|
|
|
2642
|
|
|
$modules = Jetpack::get_default_modules( $min_version, $max_version ); |
2643
|
|
|
$modules = array_merge( $other_modules, $modules ); |
2644
|
|
|
|
2645
|
|
|
// Look for standalone plugins and disable if active. |
2646
|
|
|
|
2647
|
|
|
$to_deactivate = array(); |
2648
|
|
|
foreach ( $modules as $module ) { |
2649
|
|
|
if ( isset( $jetpack->plugins_to_deactivate[$module] ) ) { |
2650
|
|
|
$to_deactivate[$module] = $jetpack->plugins_to_deactivate[$module]; |
2651
|
|
|
} |
2652
|
|
|
} |
2653
|
|
|
|
2654
|
|
|
$deactivated = array(); |
2655
|
|
|
foreach ( $to_deactivate as $module => $deactivate_me ) { |
2656
|
|
|
list( $probable_file, $probable_title ) = $deactivate_me; |
2657
|
|
|
if ( Jetpack_Client_Server::deactivate_plugin( $probable_file, $probable_title ) ) { |
2658
|
|
|
$deactivated[] = $module; |
2659
|
|
|
} |
2660
|
|
|
} |
2661
|
|
|
|
2662
|
|
|
if ( $deactivated ) { |
|
|
|
|
2663
|
|
|
Jetpack::state( 'deactivated_plugins', join( ',', $deactivated ) ); |
2664
|
|
|
|
2665
|
|
|
$url = add_query_arg( |
2666
|
|
|
array( |
2667
|
|
|
'action' => 'activate_default_modules', |
2668
|
|
|
'_wpnonce' => wp_create_nonce( 'activate_default_modules' ), |
2669
|
|
|
), |
2670
|
|
|
add_query_arg( compact( 'min_version', 'max_version', 'other_modules' ), Jetpack::admin_url( 'page=jetpack' ) ) |
2671
|
|
|
); |
2672
|
|
|
wp_safe_redirect( $url ); |
2673
|
|
|
exit; |
|
|
|
|
2674
|
|
|
} |
2675
|
|
|
|
2676
|
|
|
/** |
2677
|
|
|
* Fires before default modules are activated. |
2678
|
|
|
* |
2679
|
|
|
* @since 1.9.0 |
2680
|
|
|
* |
2681
|
|
|
* @param string $min_version Minimum version number required to use modules. |
2682
|
|
|
* @param string $max_version Maximum version number required to use modules. |
2683
|
|
|
* @param array $other_modules Array of other modules to activate alongside the default modules. |
2684
|
|
|
*/ |
2685
|
|
|
do_action( 'jetpack_before_activate_default_modules', $min_version, $max_version, $other_modules ); |
2686
|
|
|
|
2687
|
|
|
// Check each module for fatal errors, a la wp-admin/plugins.php::activate before activating |
2688
|
|
|
Jetpack::restate(); |
2689
|
|
|
Jetpack::catch_errors( true ); |
2690
|
|
|
|
2691
|
|
|
$active = Jetpack::get_active_modules(); |
2692
|
|
|
|
2693
|
|
|
foreach ( $modules as $module ) { |
2694
|
|
|
if ( did_action( "jetpack_module_loaded_$module" ) ) { |
2695
|
|
|
$active[] = $module; |
2696
|
|
|
Jetpack_Options::update_option( 'active_modules', array_unique( $active ) ); |
2697
|
|
|
continue; |
2698
|
|
|
} |
2699
|
|
|
|
2700
|
|
|
if ( in_array( $module, $active ) ) { |
2701
|
|
|
$module_info = Jetpack::get_module( $module ); |
2702
|
|
|
if ( ! $module_info['deactivate'] ) { |
2703
|
|
|
$state = in_array( $module, $other_modules ) ? 'reactivated_modules' : 'activated_modules'; |
2704
|
|
View Code Duplication |
if ( $active_state = Jetpack::state( $state ) ) { |
2705
|
|
|
$active_state = explode( ',', $active_state ); |
2706
|
|
|
} else { |
2707
|
|
|
$active_state = array(); |
2708
|
|
|
} |
2709
|
|
|
$active_state[] = $module; |
2710
|
|
|
Jetpack::state( $state, implode( ',', $active_state ) ); |
2711
|
|
|
} |
2712
|
|
|
continue; |
2713
|
|
|
} |
2714
|
|
|
|
2715
|
|
|
$file = Jetpack::get_module_path( $module ); |
2716
|
|
|
if ( ! file_exists( $file ) ) { |
2717
|
|
|
continue; |
2718
|
|
|
} |
2719
|
|
|
|
2720
|
|
|
// we'll override this later if the plugin can be included without fatal error |
2721
|
|
|
wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) ); |
2722
|
|
|
Jetpack::state( 'error', 'module_activation_failed' ); |
2723
|
|
|
Jetpack::state( 'module', $module ); |
2724
|
|
|
ob_start(); |
2725
|
|
|
require $file; |
2726
|
|
|
/** |
2727
|
|
|
* Fires when a specific module is activated. |
2728
|
|
|
* |
2729
|
|
|
* @since 1.9.0 |
2730
|
|
|
* |
2731
|
|
|
* @param string $module Module slug. |
2732
|
|
|
*/ |
2733
|
|
|
do_action( 'jetpack_activate_module', $module ); |
2734
|
|
|
$active[] = $module; |
2735
|
|
|
$state = in_array( $module, $other_modules ) ? 'reactivated_modules' : 'activated_modules'; |
2736
|
|
View Code Duplication |
if ( $active_state = Jetpack::state( $state ) ) { |
2737
|
|
|
$active_state = explode( ',', $active_state ); |
2738
|
|
|
} else { |
2739
|
|
|
$active_state = array(); |
2740
|
|
|
} |
2741
|
|
|
$active_state[] = $module; |
2742
|
|
|
Jetpack::state( $state, implode( ',', $active_state ) ); |
2743
|
|
|
Jetpack_Options::update_option( 'active_modules', array_unique( $active ) ); |
2744
|
|
|
ob_end_clean(); |
2745
|
|
|
} |
2746
|
|
|
Jetpack::state( 'error', false ); |
|
|
|
|
2747
|
|
|
Jetpack::state( 'module', false ); |
|
|
|
|
2748
|
|
|
Jetpack::catch_errors( false ); |
2749
|
|
|
/** |
2750
|
|
|
* Fires when default modules are activated. |
2751
|
|
|
* |
2752
|
|
|
* @since 1.9.0 |
2753
|
|
|
* |
2754
|
|
|
* @param string $min_version Minimum version number required to use modules. |
2755
|
|
|
* @param string $max_version Maximum version number required to use modules. |
2756
|
|
|
* @param array $other_modules Array of other modules to activate alongside the default modules. |
2757
|
|
|
*/ |
2758
|
|
|
do_action( 'jetpack_activate_default_modules', $min_version, $max_version, $other_modules ); |
2759
|
|
|
} |
2760
|
|
|
|
2761
|
|
|
public static function activate_module( $module, $exit = true, $redirect = true ) { |
2762
|
|
|
/** |
2763
|
|
|
* Fires before a module is activated. |
2764
|
|
|
* |
2765
|
|
|
* @since 2.6.0 |
2766
|
|
|
* |
2767
|
|
|
* @param string $module Module slug. |
2768
|
|
|
* @param bool $exit Should we exit after the module has been activated. Default to true. |
2769
|
|
|
* @param bool $redirect Should the user be redirected after module activation? Default to true. |
2770
|
|
|
*/ |
2771
|
|
|
do_action( 'jetpack_pre_activate_module', $module, $exit, $redirect ); |
2772
|
|
|
|
2773
|
|
|
$jetpack = Jetpack::init(); |
2774
|
|
|
|
2775
|
|
|
if ( ! strlen( $module ) ) |
2776
|
|
|
return false; |
2777
|
|
|
|
2778
|
|
|
if ( ! Jetpack::is_module( $module ) ) |
2779
|
|
|
return false; |
2780
|
|
|
|
2781
|
|
|
// If it's already active, then don't do it again |
2782
|
|
|
$active = Jetpack::get_active_modules(); |
2783
|
|
|
foreach ( $active as $act ) { |
2784
|
|
|
if ( $act == $module ) |
2785
|
|
|
return true; |
2786
|
|
|
} |
2787
|
|
|
|
2788
|
|
|
$module_data = Jetpack::get_module( $module ); |
2789
|
|
|
|
2790
|
|
|
if ( ! Jetpack::is_active() ) { |
2791
|
|
|
if ( !Jetpack::is_development_mode() ) |
2792
|
|
|
return false; |
2793
|
|
|
|
2794
|
|
|
// If we're not connected but in development mode, make sure the module doesn't require a connection |
2795
|
|
|
if ( Jetpack::is_development_mode() && $module_data['requires_connection'] ) |
2796
|
|
|
return false; |
2797
|
|
|
} |
2798
|
|
|
|
2799
|
|
|
// Check and see if the old plugin is active |
2800
|
|
|
if ( isset( $jetpack->plugins_to_deactivate[ $module ] ) ) { |
2801
|
|
|
// Deactivate the old plugin |
2802
|
|
|
if ( Jetpack_Client_Server::deactivate_plugin( $jetpack->plugins_to_deactivate[ $module ][0], $jetpack->plugins_to_deactivate[ $module ][1] ) ) { |
2803
|
|
|
// If we deactivated the old plugin, remembere that with ::state() and redirect back to this page to activate the module |
2804
|
|
|
// We can't activate the module on this page load since the newly deactivated old plugin is still loaded on this page load. |
2805
|
|
|
Jetpack::state( 'deactivated_plugins', $module ); |
2806
|
|
|
wp_safe_redirect( add_query_arg( 'jetpack_restate', 1 ) ); |
2807
|
|
|
exit; |
|
|
|
|
2808
|
|
|
} |
2809
|
|
|
} |
2810
|
|
|
|
2811
|
|
|
// Check the file for fatal errors, a la wp-admin/plugins.php::activate |
2812
|
|
|
Jetpack::state( 'module', $module ); |
2813
|
|
|
Jetpack::state( 'error', 'module_activation_failed' ); // we'll override this later if the plugin can be included without fatal error |
2814
|
|
|
|
2815
|
|
|
Jetpack::catch_errors( true ); |
2816
|
|
|
ob_start(); |
2817
|
|
|
require Jetpack::get_module_path( $module ); |
2818
|
|
|
/** This action is documented in class.jetpack.php */ |
2819
|
|
|
do_action( 'jetpack_activate_module', $module ); |
2820
|
|
|
$active[] = $module; |
2821
|
|
|
Jetpack_Options::update_option( 'active_modules', array_unique( $active ) ); |
2822
|
|
|
Jetpack::state( 'error', false ); // the override |
|
|
|
|
2823
|
|
|
Jetpack::state( 'message', 'module_activated' ); |
2824
|
|
|
Jetpack::state( 'module', $module ); |
2825
|
|
|
ob_end_clean(); |
2826
|
|
|
Jetpack::catch_errors( false ); |
2827
|
|
|
|
2828
|
|
|
// A flag for Jump Start so it's not shown again. Only set if it hasn't been yet. |
2829
|
|
View Code Duplication |
if ( 'new_connection' === Jetpack_Options::get_option( 'jumpstart' ) ) { |
2830
|
|
|
Jetpack_Options::update_option( 'jumpstart', 'jetpack_action_taken' ); |
2831
|
|
|
|
2832
|
|
|
//Jump start is being dismissed send data to MC Stats |
2833
|
|
|
$jetpack->stat( 'jumpstart', 'manual,'.$module ); |
2834
|
|
|
|
2835
|
|
|
$jetpack->do_stats( 'server_side' ); |
2836
|
|
|
} |
2837
|
|
|
|
2838
|
|
|
if ( $redirect ) { |
2839
|
|
|
wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) ); |
2840
|
|
|
} |
2841
|
|
|
if ( $exit ) { |
2842
|
|
|
exit; |
|
|
|
|
2843
|
|
|
} |
2844
|
|
|
} |
2845
|
|
|
|
2846
|
|
|
function activate_module_actions( $module ) { |
2847
|
|
|
/** |
2848
|
|
|
* Fires when a module is activated. |
2849
|
|
|
* The dynamic part of the filter, $module, is the module slug. |
2850
|
|
|
* |
2851
|
|
|
* @since 1.9.0 |
2852
|
|
|
* |
2853
|
|
|
* @param string $module Module slug. |
2854
|
|
|
*/ |
2855
|
|
|
do_action( "jetpack_activate_module_$module", $module ); |
2856
|
|
|
|
2857
|
|
|
$this->sync->sync_all_module_options( $module ); |
2858
|
|
|
} |
2859
|
|
|
|
2860
|
|
|
public static function deactivate_module( $module ) { |
2861
|
|
|
/** |
2862
|
|
|
* Fires when a module is deactivated. |
2863
|
|
|
* |
2864
|
|
|
* @since 1.9.0 |
2865
|
|
|
* |
2866
|
|
|
* @param string $module Module slug. |
2867
|
|
|
*/ |
2868
|
|
|
do_action( 'jetpack_pre_deactivate_module', $module ); |
2869
|
|
|
|
2870
|
|
|
$jetpack = Jetpack::init(); |
2871
|
|
|
|
2872
|
|
|
$active = Jetpack::get_active_modules(); |
2873
|
|
|
$new = array_filter( array_diff( $active, (array) $module ) ); |
2874
|
|
|
|
2875
|
|
|
/** |
2876
|
|
|
* Fires when a module is deactivated. |
2877
|
|
|
* The dynamic part of the filter, $module, is the module slug. |
2878
|
|
|
* |
2879
|
|
|
* @since 1.9.0 |
2880
|
|
|
* |
2881
|
|
|
* @param string $module Module slug. |
2882
|
|
|
*/ |
2883
|
|
|
do_action( "jetpack_deactivate_module_$module", $module ); |
2884
|
|
|
|
2885
|
|
|
// A flag for Jump Start so it's not shown again. |
2886
|
|
View Code Duplication |
if ( 'new_connection' === Jetpack_Options::get_option( 'jumpstart' ) ) { |
2887
|
|
|
Jetpack_Options::update_option( 'jumpstart', 'jetpack_action_taken' ); |
2888
|
|
|
|
2889
|
|
|
//Jump start is being dismissed send data to MC Stats |
2890
|
|
|
$jetpack->stat( 'jumpstart', 'manual,deactivated-'.$module ); |
2891
|
|
|
|
2892
|
|
|
$jetpack->do_stats( 'server_side' ); |
2893
|
|
|
} |
2894
|
|
|
|
2895
|
|
|
return Jetpack_Options::update_option( 'active_modules', array_unique( $new ) ); |
2896
|
|
|
} |
2897
|
|
|
|
2898
|
|
|
public static function enable_module_configurable( $module ) { |
2899
|
|
|
$module = Jetpack::get_module_slug( $module ); |
2900
|
|
|
add_filter( 'jetpack_module_configurable_' . $module, '__return_true' ); |
2901
|
|
|
} |
2902
|
|
|
|
2903
|
|
|
public static function module_configuration_url( $module ) { |
2904
|
|
|
$module = Jetpack::get_module_slug( $module ); |
2905
|
|
|
return Jetpack::admin_url( array( 'page' => 'jetpack', 'configure' => $module ) ); |
2906
|
|
|
} |
2907
|
|
|
|
2908
|
|
|
public static function module_configuration_load( $module, $method ) { |
2909
|
|
|
$module = Jetpack::get_module_slug( $module ); |
2910
|
|
|
add_action( 'jetpack_module_configuration_load_' . $module, $method ); |
2911
|
|
|
} |
2912
|
|
|
|
2913
|
|
|
public static function module_configuration_head( $module, $method ) { |
2914
|
|
|
$module = Jetpack::get_module_slug( $module ); |
2915
|
|
|
add_action( 'jetpack_module_configuration_head_' . $module, $method ); |
2916
|
|
|
} |
2917
|
|
|
|
2918
|
|
|
public static function module_configuration_screen( $module, $method ) { |
2919
|
|
|
$module = Jetpack::get_module_slug( $module ); |
2920
|
|
|
add_action( 'jetpack_module_configuration_screen_' . $module, $method ); |
2921
|
|
|
} |
2922
|
|
|
|
2923
|
|
|
public static function module_configuration_activation_screen( $module, $method ) { |
2924
|
|
|
$module = Jetpack::get_module_slug( $module ); |
2925
|
|
|
add_action( 'display_activate_module_setting_' . $module, $method ); |
2926
|
|
|
} |
2927
|
|
|
|
2928
|
|
|
/* Installation */ |
2929
|
|
|
|
2930
|
|
|
public static function bail_on_activation( $message, $deactivate = true ) { |
2931
|
|
|
?> |
2932
|
|
|
<!doctype html> |
2933
|
|
|
<html> |
2934
|
|
|
<head> |
2935
|
|
|
<meta charset="<?php bloginfo( 'charset' ); ?>"> |
2936
|
|
|
<style> |
2937
|
|
|
* { |
2938
|
|
|
text-align: center; |
2939
|
|
|
margin: 0; |
2940
|
|
|
padding: 0; |
2941
|
|
|
font-family: "Lucida Grande",Verdana,Arial,"Bitstream Vera Sans",sans-serif; |
2942
|
|
|
} |
2943
|
|
|
p { |
2944
|
|
|
margin-top: 1em; |
2945
|
|
|
font-size: 18px; |
2946
|
|
|
} |
2947
|
|
|
</style> |
2948
|
|
|
<body> |
2949
|
|
|
<p><?php echo esc_html( $message ); ?></p> |
2950
|
|
|
</body> |
2951
|
|
|
</html> |
2952
|
|
|
<?php |
2953
|
|
|
if ( $deactivate ) { |
2954
|
|
|
$plugins = get_option( 'active_plugins' ); |
2955
|
|
|
$jetpack = plugin_basename( JETPACK__PLUGIN_DIR . 'jetpack.php' ); |
2956
|
|
|
$update = false; |
2957
|
|
|
foreach ( $plugins as $i => $plugin ) { |
2958
|
|
|
if ( $plugin === $jetpack ) { |
2959
|
|
|
$plugins[$i] = false; |
2960
|
|
|
$update = true; |
2961
|
|
|
} |
2962
|
|
|
} |
2963
|
|
|
|
2964
|
|
|
if ( $update ) { |
2965
|
|
|
update_option( 'active_plugins', array_filter( $plugins ) ); |
2966
|
|
|
} |
2967
|
|
|
} |
2968
|
|
|
exit; |
|
|
|
|
2969
|
|
|
} |
2970
|
|
|
|
2971
|
|
|
/** |
2972
|
|
|
* Attached to activate_{ plugin_basename( __FILES__ ) } by register_activation_hook() |
2973
|
|
|
* @static |
2974
|
|
|
*/ |
2975
|
|
|
public static function plugin_activation( $network_wide ) { |
2976
|
|
|
Jetpack_Options::update_option( 'activated', 1 ); |
2977
|
|
|
|
2978
|
|
|
if ( version_compare( $GLOBALS['wp_version'], JETPACK__MINIMUM_WP_VERSION, '<' ) ) { |
2979
|
|
|
Jetpack::bail_on_activation( sprintf( __( 'Jetpack requires WordPress version %s or later.', 'jetpack' ), JETPACK__MINIMUM_WP_VERSION ) ); |
2980
|
|
|
} |
2981
|
|
|
|
2982
|
|
|
if ( $network_wide ) |
2983
|
|
|
Jetpack::state( 'network_nag', true ); |
|
|
|
|
2984
|
|
|
|
2985
|
|
|
Jetpack::plugin_initialize(); |
2986
|
|
|
} |
2987
|
|
|
/** |
2988
|
|
|
* Runs before bumping version numbers up to a new version |
2989
|
|
|
* @param (string) $version Version:timestamp |
2990
|
|
|
* @param (string) $old_version Old Version:timestamp or false if not set yet. |
2991
|
|
|
* @return null [description] |
2992
|
|
|
*/ |
2993
|
|
|
public static function do_version_bump( $version, $old_version ) { |
2994
|
|
|
|
2995
|
|
|
if ( ! $old_version ) { // For new sites |
2996
|
|
|
// Setting up jetpack manage |
2997
|
|
|
Jetpack::activate_manage(); |
2998
|
|
|
} |
2999
|
|
|
} |
3000
|
|
|
|
3001
|
|
|
/** |
3002
|
|
|
* Sets the internal version number and activation state. |
3003
|
|
|
* @static |
3004
|
|
|
*/ |
3005
|
|
|
public static function plugin_initialize() { |
3006
|
|
|
if ( ! Jetpack_Options::get_option( 'activated' ) ) { |
3007
|
|
|
Jetpack_Options::update_option( 'activated', 2 ); |
3008
|
|
|
} |
3009
|
|
|
|
3010
|
|
View Code Duplication |
if ( ! Jetpack_Options::get_option( 'version' ) ) { |
3011
|
|
|
$version = $old_version = JETPACK__VERSION . ':' . time(); |
3012
|
|
|
/** This action is documented in class.jetpack.php */ |
3013
|
|
|
do_action( 'updating_jetpack_version', $version, false ); |
3014
|
|
|
Jetpack_Options::update_options( compact( 'version', 'old_version' ) ); |
3015
|
|
|
} |
3016
|
|
|
|
3017
|
|
|
Jetpack::load_modules(); |
3018
|
|
|
|
3019
|
|
|
Jetpack_Options::delete_option( 'do_activate' ); |
3020
|
|
|
} |
3021
|
|
|
|
3022
|
|
|
/** |
3023
|
|
|
* Removes all connection options |
3024
|
|
|
* @static |
3025
|
|
|
*/ |
3026
|
|
|
public static function plugin_deactivation( ) { |
3027
|
|
|
require_once( ABSPATH . '/wp-admin/includes/plugin.php' ); |
3028
|
|
|
if( is_plugin_active_for_network( 'jetpack/jetpack.php' ) ) { |
3029
|
|
|
Jetpack_Network::init()->deactivate(); |
3030
|
|
|
} else { |
3031
|
|
|
Jetpack::disconnect( false ); |
3032
|
|
|
//Jetpack_Heartbeat::init()->deactivate(); |
3033
|
|
|
} |
3034
|
|
|
} |
3035
|
|
|
|
3036
|
|
|
/** |
3037
|
|
|
* Disconnects from the Jetpack servers. |
3038
|
|
|
* Forgets all connection details and tells the Jetpack servers to do the same. |
3039
|
|
|
* @static |
3040
|
|
|
*/ |
3041
|
|
|
public static function disconnect( $update_activated_state = true ) { |
3042
|
|
|
wp_clear_scheduled_hook( 'jetpack_clean_nonces' ); |
3043
|
|
|
Jetpack::clean_nonces( true ); |
3044
|
|
|
|
3045
|
|
|
Jetpack::load_xml_rpc_client(); |
3046
|
|
|
$xml = new Jetpack_IXR_Client(); |
3047
|
|
|
$xml->query( 'jetpack.deregister' ); |
3048
|
|
|
|
3049
|
|
|
Jetpack_Options::delete_option( |
3050
|
|
|
array( |
3051
|
|
|
'register', |
3052
|
|
|
'blog_token', |
3053
|
|
|
'user_token', |
3054
|
|
|
'user_tokens', |
3055
|
|
|
'master_user', |
3056
|
|
|
'time_diff', |
3057
|
|
|
'fallback_no_verify_ssl_certs', |
3058
|
|
|
) |
3059
|
|
|
); |
3060
|
|
|
|
3061
|
|
|
if ( $update_activated_state ) { |
3062
|
|
|
Jetpack_Options::update_option( 'activated', 4 ); |
3063
|
|
|
} |
3064
|
|
|
|
3065
|
|
|
$jetpack_unique_connection = Jetpack_Options::get_option( 'unique_connection' ); |
3066
|
|
|
// Check then record unique disconnection if site has never been disconnected previously |
3067
|
|
|
if ( -1 == $jetpack_unique_connection['disconnected'] ) { |
3068
|
|
|
$jetpack_unique_connection['disconnected'] = 1; |
3069
|
|
|
} |
3070
|
|
|
else { |
3071
|
|
|
if ( 0 == $jetpack_unique_connection['disconnected'] ) { |
3072
|
|
|
//track unique disconnect |
3073
|
|
|
$jetpack = Jetpack::init(); |
3074
|
|
|
|
3075
|
|
|
$jetpack->stat( 'connections', 'unique-disconnect' ); |
3076
|
|
|
$jetpack->do_stats( 'server_side' ); |
3077
|
|
|
} |
3078
|
|
|
// increment number of times disconnected |
3079
|
|
|
$jetpack_unique_connection['disconnected'] += 1; |
3080
|
|
|
} |
3081
|
|
|
|
3082
|
|
|
Jetpack_Options::update_option( 'unique_connection', $jetpack_unique_connection ); |
3083
|
|
|
|
3084
|
|
|
// Disable the Heartbeat cron |
3085
|
|
|
Jetpack_Heartbeat::init()->deactivate(); |
3086
|
|
|
} |
3087
|
|
|
|
3088
|
|
|
/** |
3089
|
|
|
* Unlinks the current user from the linked WordPress.com user |
3090
|
|
|
*/ |
3091
|
|
|
public static function unlink_user( $user_id = null ) { |
3092
|
|
|
if ( ! $tokens = Jetpack_Options::get_option( 'user_tokens' ) ) |
3093
|
|
|
return false; |
3094
|
|
|
|
3095
|
|
|
$user_id = empty( $user_id ) ? get_current_user_id() : intval( $user_id ); |
3096
|
|
|
|
3097
|
|
|
if ( Jetpack_Options::get_option( 'master_user' ) == $user_id ) |
3098
|
|
|
return false; |
3099
|
|
|
|
3100
|
|
|
if ( ! isset( $tokens[ $user_id ] ) ) |
3101
|
|
|
return false; |
3102
|
|
|
|
3103
|
|
|
Jetpack::load_xml_rpc_client(); |
3104
|
|
|
$xml = new Jetpack_IXR_Client( compact( 'user_id' ) ); |
3105
|
|
|
$xml->query( 'jetpack.unlink_user', $user_id ); |
3106
|
|
|
|
3107
|
|
|
unset( $tokens[ $user_id ] ); |
3108
|
|
|
|
3109
|
|
|
Jetpack_Options::update_option( 'user_tokens', $tokens ); |
3110
|
|
|
|
3111
|
|
|
return true; |
3112
|
|
|
} |
3113
|
|
|
|
3114
|
|
|
/** |
3115
|
|
|
* Attempts Jetpack registration. If it fail, a state flag is set: @see ::admin_page_load() |
3116
|
|
|
*/ |
3117
|
|
|
public static function try_registration() { |
3118
|
|
|
// Let's get some testing in beta versions and such. |
3119
|
|
|
if ( self::is_development_version() && defined( 'PHP_URL_HOST' ) ) { |
3120
|
|
|
// Before attempting to connect, let's make sure that the domains are viable. |
3121
|
|
|
$domains_to_check = array_unique( array( |
3122
|
|
|
'siteurl' => parse_url( get_site_url(), PHP_URL_HOST ), |
3123
|
|
|
'homeurl' => parse_url( get_home_url(), PHP_URL_HOST ), |
3124
|
|
|
) ); |
3125
|
|
|
foreach ( $domains_to_check as $domain ) { |
3126
|
|
|
$result = Jetpack_Data::is_usable_domain( $domain ); |
3127
|
|
|
if ( is_wp_error( $result ) ) { |
3128
|
|
|
return $result; |
3129
|
|
|
} |
3130
|
|
|
} |
3131
|
|
|
} |
3132
|
|
|
|
3133
|
|
|
$result = Jetpack::register(); |
3134
|
|
|
|
3135
|
|
|
// If there was an error with registration and the site was not registered, record this so we can show a message. |
3136
|
|
|
if ( ! $result || is_wp_error( $result ) ) { |
3137
|
|
|
return $result; |
3138
|
|
|
} else { |
3139
|
|
|
return true; |
3140
|
|
|
} |
3141
|
|
|
} |
3142
|
|
|
|
3143
|
|
|
/** |
3144
|
|
|
* Tracking an internal event log. Try not to put too much chaff in here. |
3145
|
|
|
* |
3146
|
|
|
* [Everyone Loves a Log!](https://www.youtube.com/watch?v=2C7mNr5WMjA) |
3147
|
|
|
*/ |
3148
|
|
|
public static function log( $code, $data = null ) { |
3149
|
|
|
// only grab the latest 200 entries |
3150
|
|
|
$log = array_slice( Jetpack_Options::get_option( 'log', array() ), -199, 199 ); |
3151
|
|
|
|
3152
|
|
|
// Append our event to the log |
3153
|
|
|
$log_entry = array( |
3154
|
|
|
'time' => time(), |
3155
|
|
|
'user_id' => get_current_user_id(), |
3156
|
|
|
'blog_id' => Jetpack_Options::get_option( 'id' ), |
3157
|
|
|
'code' => $code, |
3158
|
|
|
); |
3159
|
|
|
// Don't bother storing it unless we've got some. |
3160
|
|
|
if ( ! is_null( $data ) ) { |
3161
|
|
|
$log_entry['data'] = $data; |
3162
|
|
|
} |
3163
|
|
|
$log[] = $log_entry; |
3164
|
|
|
|
3165
|
|
|
// Try add_option first, to make sure it's not autoloaded. |
3166
|
|
|
// @todo: Add an add_option method to Jetpack_Options |
|
|
|
|
3167
|
|
|
if ( ! add_option( 'jetpack_log', $log, null, 'no' ) ) { |
3168
|
|
|
Jetpack_Options::update_option( 'log', $log ); |
3169
|
|
|
} |
3170
|
|
|
|
3171
|
|
|
/** |
3172
|
|
|
* Fires when Jetpack logs an internal event. |
3173
|
|
|
* |
3174
|
|
|
* @since 3.0.0 |
3175
|
|
|
* |
3176
|
|
|
* @param array $log_entry { |
3177
|
|
|
* Array of details about the log entry. |
3178
|
|
|
* |
3179
|
|
|
* @param string time Time of the event. |
3180
|
|
|
* @param int user_id ID of the user who trigerred the event. |
3181
|
|
|
* @param int blog_id Jetpack Blog ID. |
3182
|
|
|
* @param string code Unique name for the event. |
3183
|
|
|
* @param string data Data about the event. |
3184
|
|
|
* } |
3185
|
|
|
*/ |
3186
|
|
|
do_action( 'jetpack_log_entry', $log_entry ); |
3187
|
|
|
} |
3188
|
|
|
|
3189
|
|
|
/** |
3190
|
|
|
* Get the internal event log. |
3191
|
|
|
* |
3192
|
|
|
* @param $event (string) - only return the specific log events |
3193
|
|
|
* @param $num (int) - get specific number of latest results, limited to 200 |
3194
|
|
|
* |
3195
|
|
|
* @return array of log events || WP_Error for invalid params |
3196
|
|
|
*/ |
3197
|
|
|
public static function get_log( $event = false, $num = false ) { |
3198
|
|
|
if ( $event && ! is_string( $event ) ) { |
3199
|
|
|
return new WP_Error( __( 'First param must be string or empty', 'jetpack' ) ); |
3200
|
|
|
} |
3201
|
|
|
|
3202
|
|
|
if ( $num && ! is_numeric( $num ) ) { |
3203
|
|
|
return new WP_Error( __( 'Second param must be numeric or empty', 'jetpack' ) ); |
3204
|
|
|
} |
3205
|
|
|
|
3206
|
|
|
$entire_log = Jetpack_Options::get_option( 'log', array() ); |
3207
|
|
|
|
3208
|
|
|
// If nothing set - act as it did before, otherwise let's start customizing the output |
3209
|
|
|
if ( ! $num && ! $event ) { |
3210
|
|
|
return $entire_log; |
3211
|
|
|
} else { |
3212
|
|
|
$entire_log = array_reverse( $entire_log ); |
3213
|
|
|
} |
3214
|
|
|
|
3215
|
|
|
$custom_log_output = array(); |
3216
|
|
|
|
3217
|
|
|
if ( $event ) { |
3218
|
|
|
foreach ( $entire_log as $log_event ) { |
3219
|
|
|
if ( $event == $log_event[ 'code' ] ) { |
3220
|
|
|
$custom_log_output[] = $log_event; |
3221
|
|
|
} |
3222
|
|
|
} |
3223
|
|
|
} else { |
3224
|
|
|
$custom_log_output = $entire_log; |
3225
|
|
|
} |
3226
|
|
|
|
3227
|
|
|
if ( $num ) { |
3228
|
|
|
$custom_log_output = array_slice( $custom_log_output, 0, $num ); |
3229
|
|
|
} |
3230
|
|
|
|
3231
|
|
|
return $custom_log_output; |
3232
|
|
|
} |
3233
|
|
|
|
3234
|
|
|
/** |
3235
|
|
|
* Log modification of important settings. |
3236
|
|
|
*/ |
3237
|
|
|
public static function log_settings_change( $option, $old_value, $value ) { |
3238
|
|
|
switch( $option ) { |
3239
|
|
|
case 'jetpack_sync_non_public_post_stati': |
3240
|
|
|
self::log( $option, $value ); |
3241
|
|
|
break; |
3242
|
|
|
} |
3243
|
|
|
} |
3244
|
|
|
|
3245
|
|
|
/** |
3246
|
|
|
* Return stat data for WPCOM sync |
3247
|
|
|
*/ |
3248
|
|
|
function get_stat_data() { |
3249
|
|
|
$heartbeat_data = Jetpack_Heartbeat::generate_stats_array(); |
3250
|
|
|
$additional_data = $this->get_additional_stat_data(); |
3251
|
|
|
|
3252
|
|
|
return json_encode( array_merge( $heartbeat_data, $additional_data ) ); |
3253
|
|
|
} |
3254
|
|
|
|
3255
|
|
|
/** |
3256
|
|
|
* Get additional stat data to sync to WPCOM |
3257
|
|
|
*/ |
3258
|
|
|
function get_additional_stat_data( $prefix = '' ) { |
3259
|
|
|
$return["{$prefix}themes"] = Jetpack::get_parsed_theme_data(); |
|
|
|
|
3260
|
|
|
$return["{$prefix}plugins-extra"] = Jetpack::get_parsed_plugin_data(); |
3261
|
|
|
$return["{$prefix}users"] = count_users(); |
3262
|
|
|
$return["{$prefix}site-count"] = 0; |
3263
|
|
|
if ( function_exists( 'get_blog_count' ) ) { |
3264
|
|
|
$return["{$prefix}site-count"] = get_blog_count(); |
3265
|
|
|
} |
3266
|
|
|
return $return; |
3267
|
|
|
} |
3268
|
|
|
|
3269
|
|
|
/* Admin Pages */ |
3270
|
|
|
|
3271
|
|
|
function admin_init() { |
3272
|
|
|
// If the plugin is not connected, display a connect message. |
3273
|
|
|
if ( |
3274
|
|
|
// the plugin was auto-activated and needs its candy |
3275
|
|
|
Jetpack_Options::get_option( 'do_activate' ) |
3276
|
|
|
|| |
3277
|
|
|
// the plugin is active, but was never activated. Probably came from a site-wide network activation |
3278
|
|
|
! Jetpack_Options::get_option( 'activated' ) |
3279
|
|
|
) { |
3280
|
|
|
Jetpack::plugin_initialize(); |
3281
|
|
|
} |
3282
|
|
|
|
3283
|
|
|
if ( ! Jetpack::is_active() && ! Jetpack::is_development_mode() ) { |
3284
|
|
|
if ( 4 != Jetpack_Options::get_option( 'activated' ) ) { |
3285
|
|
|
// Show connect notice on dashboard and plugins pages |
3286
|
|
|
add_action( 'load-index.php', array( $this, 'prepare_connect_notice' ) ); |
3287
|
|
|
add_action( 'load-plugins.php', array( $this, 'prepare_connect_notice' ) ); |
3288
|
|
|
} |
3289
|
|
|
} elseif ( false === Jetpack_Options::get_option( 'fallback_no_verify_ssl_certs' ) ) { |
3290
|
|
|
// Upgrade: 1.1 -> 1.1.1 |
3291
|
|
|
// Check and see if host can verify the Jetpack servers' SSL certificate |
3292
|
|
|
$args = array(); |
3293
|
|
|
Jetpack_Client::_wp_remote_request( |
3294
|
|
|
Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'test' ) ), |
3295
|
|
|
$args, |
3296
|
|
|
true |
3297
|
|
|
); |
3298
|
|
|
} else { |
3299
|
|
|
// Show the notice on the Dashboard only for now |
3300
|
|
|
|
3301
|
|
|
add_action( 'load-index.php', array( $this, 'prepare_manage_jetpack_notice' ) ); |
3302
|
|
|
|
3303
|
|
|
// Identity crisis notices |
3304
|
|
|
add_action( 'jetpack_notices', array( $this, 'alert_identity_crisis' ) ); |
3305
|
|
|
} |
3306
|
|
|
|
3307
|
|
|
// If the plugin has just been disconnected from WP.com, show the survey notice |
3308
|
|
|
if ( isset( $_GET['disconnected'] ) && 'true' === $_GET['disconnected'] ) { |
3309
|
|
|
add_action( 'jetpack_notices', array( $this, 'disconnect_survey_notice' ) ); |
3310
|
|
|
} |
3311
|
|
|
|
3312
|
|
|
if ( current_user_can( 'manage_options' ) && 'ALWAYS' == JETPACK_CLIENT__HTTPS && ! self::permit_ssl() ) { |
3313
|
|
|
add_action( 'admin_notices', array( $this, 'alert_required_ssl_fail' ) ); |
3314
|
|
|
} |
3315
|
|
|
|
3316
|
|
|
add_action( 'load-plugins.php', array( $this, 'intercept_plugin_error_scrape_init' ) ); |
3317
|
|
|
add_action( 'admin_enqueue_scripts', array( $this, 'admin_menu_css' ) ); |
3318
|
|
|
add_filter( 'plugin_action_links_' . plugin_basename( JETPACK__PLUGIN_DIR . 'jetpack.php' ), array( $this, 'plugin_action_links' ) ); |
3319
|
|
|
|
3320
|
|
|
if ( Jetpack::is_active() || Jetpack::is_development_mode() ) { |
3321
|
|
|
// Artificially throw errors in certain whitelisted cases during plugin activation |
3322
|
|
|
add_action( 'activate_plugin', array( $this, 'throw_error_on_activate_plugin' ) ); |
3323
|
|
|
|
3324
|
|
|
// Kick off synchronization of user role when it changes |
3325
|
|
|
add_action( 'set_user_role', array( $this, 'user_role_change' ) ); |
3326
|
|
|
} |
3327
|
|
|
|
3328
|
|
|
// Jetpack Manage Activation Screen from .com |
3329
|
|
|
Jetpack::module_configuration_activation_screen( 'manage', array( $this, 'manage_activate_screen' ) ); |
3330
|
|
|
} |
3331
|
|
|
|
3332
|
|
|
function admin_body_class( $admin_body_class = '' ) { |
3333
|
|
|
$classes = explode( ' ', trim( $admin_body_class ) ); |
3334
|
|
|
|
3335
|
|
|
$classes[] = self::is_active() ? 'jetpack-connected' : 'jetpack-disconnected'; |
3336
|
|
|
|
3337
|
|
|
$admin_body_class = implode( ' ', array_unique( $classes ) ); |
3338
|
|
|
return " $admin_body_class "; |
3339
|
|
|
} |
3340
|
|
|
|
3341
|
|
|
static function add_jetpack_pagestyles( $admin_body_class = '' ) { |
3342
|
|
|
return $admin_body_class . ' jetpack-pagestyles '; |
3343
|
|
|
} |
3344
|
|
|
|
3345
|
|
|
function prepare_connect_notice() { |
3346
|
|
|
add_action( 'admin_print_styles', array( $this, 'admin_banner_styles' ) ); |
3347
|
|
|
|
3348
|
|
|
add_action( 'admin_notices', array( $this, 'admin_connect_notice' ) ); |
3349
|
|
|
|
3350
|
|
|
if ( Jetpack::state( 'network_nag' ) ) |
3351
|
|
|
add_action( 'network_admin_notices', array( $this, 'network_connect_notice' ) ); |
3352
|
|
|
} |
3353
|
|
|
/** |
3354
|
|
|
* Call this function if you want the Big Jetpack Manage Notice to show up. |
3355
|
|
|
* |
3356
|
|
|
* @return null |
3357
|
|
|
*/ |
3358
|
|
|
function prepare_manage_jetpack_notice() { |
3359
|
|
|
|
3360
|
|
|
add_action( 'admin_print_styles', array( $this, 'admin_banner_styles' ) ); |
3361
|
|
|
add_action( 'admin_notices', array( $this, 'admin_jetpack_manage_notice' ) ); |
3362
|
|
|
} |
3363
|
|
|
|
3364
|
|
|
function manage_activate_screen() { |
3365
|
|
|
include ( JETPACK__PLUGIN_DIR . 'modules/manage/activate-admin.php' ); |
3366
|
|
|
} |
3367
|
|
|
/** |
3368
|
|
|
* Sometimes a plugin can activate without causing errors, but it will cause errors on the next page load. |
3369
|
|
|
* This function artificially throws errors for such cases (whitelisted). |
3370
|
|
|
* |
3371
|
|
|
* @param string $plugin The activated plugin. |
3372
|
|
|
*/ |
3373
|
|
|
function throw_error_on_activate_plugin( $plugin ) { |
3374
|
|
|
$active_modules = Jetpack::get_active_modules(); |
3375
|
|
|
|
3376
|
|
|
// The Shortlinks module and the Stats plugin conflict, but won't cause errors on activation because of some function_exists() checks. |
3377
|
|
|
if ( function_exists( 'stats_get_api_key' ) && in_array( 'shortlinks', $active_modules ) ) { |
3378
|
|
|
$throw = false; |
3379
|
|
|
|
3380
|
|
|
// Try and make sure it really was the stats plugin |
3381
|
|
|
if ( ! class_exists( 'ReflectionFunction' ) ) { |
3382
|
|
|
if ( 'stats.php' == basename( $plugin ) ) { |
3383
|
|
|
$throw = true; |
3384
|
|
|
} |
3385
|
|
|
} else { |
3386
|
|
|
$reflection = new ReflectionFunction( 'stats_get_api_key' ); |
3387
|
|
|
if ( basename( $plugin ) == basename( $reflection->getFileName() ) ) { |
3388
|
|
|
$throw = true; |
3389
|
|
|
} |
3390
|
|
|
} |
3391
|
|
|
|
3392
|
|
|
if ( $throw ) { |
3393
|
|
|
trigger_error( sprintf( __( 'Jetpack contains the most recent version of the old “%1$s” plugin.', 'jetpack' ), 'WordPress.com Stats' ), E_USER_ERROR ); |
3394
|
|
|
} |
3395
|
|
|
} |
3396
|
|
|
} |
3397
|
|
|
|
3398
|
|
|
function intercept_plugin_error_scrape_init() { |
3399
|
|
|
add_action( 'check_admin_referer', array( $this, 'intercept_plugin_error_scrape' ), 10, 2 ); |
3400
|
|
|
} |
3401
|
|
|
|
3402
|
|
|
function intercept_plugin_error_scrape( $action, $result ) { |
3403
|
|
|
if ( ! $result ) { |
3404
|
|
|
return; |
3405
|
|
|
} |
3406
|
|
|
|
3407
|
|
|
foreach ( $this->plugins_to_deactivate as $deactivate_me ) { |
3408
|
|
|
if ( "plugin-activation-error_{$deactivate_me[0]}" == $action ) { |
3409
|
|
|
Jetpack::bail_on_activation( sprintf( __( 'Jetpack contains the most recent version of the old “%1$s” plugin.', 'jetpack' ), $deactivate_me[1] ), false ); |
3410
|
|
|
} |
3411
|
|
|
} |
3412
|
|
|
} |
3413
|
|
|
|
3414
|
|
|
function add_remote_request_handlers() { |
3415
|
|
|
add_action( 'wp_ajax_nopriv_jetpack_upload_file', array( $this, 'remote_request_handlers' ) ); |
3416
|
|
|
} |
3417
|
|
|
|
3418
|
|
|
function remote_request_handlers() { |
3419
|
|
|
switch ( current_filter() ) { |
3420
|
|
|
case 'wp_ajax_nopriv_jetpack_upload_file' : |
3421
|
|
|
$response = $this->upload_handler(); |
3422
|
|
|
break; |
3423
|
|
|
default : |
|
|
|
|
3424
|
|
|
$response = new Jetpack_Error( 'unknown_handler', 'Unknown Handler', 400 ); |
3425
|
|
|
break; |
3426
|
|
|
} |
3427
|
|
|
|
3428
|
|
|
if ( ! $response ) { |
3429
|
|
|
$response = new Jetpack_Error( 'unknown_error', 'Unknown Error', 400 ); |
3430
|
|
|
} |
3431
|
|
|
|
3432
|
|
|
if ( is_wp_error( $response ) ) { |
3433
|
|
|
$status_code = $response->get_error_data(); |
3434
|
|
|
$error = $response->get_error_code(); |
3435
|
|
|
$error_description = $response->get_error_message(); |
3436
|
|
|
|
3437
|
|
|
if ( ! is_int( $status_code ) ) { |
3438
|
|
|
$status_code = 400; |
3439
|
|
|
} |
3440
|
|
|
|
3441
|
|
|
status_header( $status_code ); |
3442
|
|
|
die( json_encode( (object) compact( 'error', 'error_description' ) ) ); |
|
|
|
|
3443
|
|
|
} |
3444
|
|
|
|
3445
|
|
|
status_header( 200 ); |
3446
|
|
|
if ( true === $response ) { |
3447
|
|
|
exit; |
|
|
|
|
3448
|
|
|
} |
3449
|
|
|
|
3450
|
|
|
die( json_encode( (object) $response ) ); |
|
|
|
|
3451
|
|
|
} |
3452
|
|
|
|
3453
|
|
|
function upload_handler() { |
3454
|
|
|
if ( 'POST' !== strtoupper( $_SERVER['REQUEST_METHOD'] ) ) { |
3455
|
|
|
return new Jetpack_Error( 405, get_status_header_desc( 405 ), 405 ); |
3456
|
|
|
} |
3457
|
|
|
|
3458
|
|
|
$user = wp_authenticate( '', '' ); |
3459
|
|
|
if ( ! $user || is_wp_error( $user ) ) { |
3460
|
|
|
return new Jetpack_Error( 403, get_status_header_desc( 403 ), 403 ); |
3461
|
|
|
} |
3462
|
|
|
|
3463
|
|
|
wp_set_current_user( $user->ID ); |
3464
|
|
|
|
3465
|
|
|
if ( ! current_user_can( 'upload_files' ) ) { |
3466
|
|
|
return new Jetpack_Error( 'cannot_upload_files', 'User does not have permission to upload files', 403 ); |
3467
|
|
|
} |
3468
|
|
|
|
3469
|
|
|
if ( empty( $_FILES ) ) { |
3470
|
|
|
return new Jetpack_Error( 'no_files_uploaded', 'No files were uploaded: nothing to process', 400 ); |
3471
|
|
|
} |
3472
|
|
|
|
3473
|
|
|
foreach ( array_keys( $_FILES ) as $files_key ) { |
3474
|
|
|
if ( ! isset( $_POST["_jetpack_file_hmac_{$files_key}"] ) ) { |
3475
|
|
|
return new Jetpack_Error( 'missing_hmac', 'An HMAC for one or more files is missing', 400 ); |
3476
|
|
|
} |
3477
|
|
|
} |
3478
|
|
|
|
3479
|
|
|
$media_keys = array_keys( $_FILES['media'] ); |
3480
|
|
|
|
3481
|
|
|
$token = Jetpack_Data::get_access_token( get_current_user_id() ); |
3482
|
|
|
if ( ! $token || is_wp_error( $token ) ) { |
3483
|
|
|
return new Jetpack_Error( 'unknown_token', 'Unknown Jetpack token', 403 ); |
3484
|
|
|
} |
3485
|
|
|
|
3486
|
|
|
$uploaded_files = array(); |
3487
|
|
|
$global_post = isset( $GLOBALS['post'] ) ? $GLOBALS['post'] : null; |
3488
|
|
|
unset( $GLOBALS['post'] ); |
3489
|
|
|
foreach ( $_FILES['media']['name'] as $index => $name ) { |
3490
|
|
|
$file = array(); |
3491
|
|
|
foreach ( $media_keys as $media_key ) { |
3492
|
|
|
$file[$media_key] = $_FILES['media'][$media_key][$index]; |
3493
|
|
|
} |
3494
|
|
|
|
3495
|
|
|
list( $hmac_provided, $salt ) = explode( ':', $_POST['_jetpack_file_hmac_media'][$index] ); |
3496
|
|
|
|
3497
|
|
|
$hmac_file = hash_hmac_file( 'sha1', $file['tmp_name'], $salt . $token->secret ); |
3498
|
|
|
if ( $hmac_provided !== $hmac_file ) { |
3499
|
|
|
$uploaded_files[$index] = (object) array( 'error' => 'invalid_hmac', 'error_description' => 'The corresponding HMAC for this file does not match' ); |
3500
|
|
|
continue; |
3501
|
|
|
} |
3502
|
|
|
|
3503
|
|
|
$_FILES['.jetpack.upload.'] = $file; |
3504
|
|
|
$post_id = isset( $_POST['post_id'][$index] ) ? absint( $_POST['post_id'][$index] ) : 0; |
3505
|
|
|
if ( ! current_user_can( 'edit_post', $post_id ) ) { |
3506
|
|
|
$post_id = 0; |
3507
|
|
|
} |
3508
|
|
|
$attachment_id = media_handle_upload( |
3509
|
|
|
'.jetpack.upload.', |
3510
|
|
|
$post_id, |
3511
|
|
|
array(), |
3512
|
|
|
array( |
3513
|
|
|
'action' => 'jetpack_upload_file', |
3514
|
|
|
) |
3515
|
|
|
); |
3516
|
|
|
|
3517
|
|
|
if ( ! $attachment_id ) { |
3518
|
|
|
$uploaded_files[$index] = (object) array( 'error' => 'unknown', 'error_description' => 'An unknown problem occurred processing the upload on the Jetpack site' ); |
3519
|
|
|
} elseif ( is_wp_error( $attachment_id ) ) { |
3520
|
|
|
$uploaded_files[$index] = (object) array( 'error' => 'attachment_' . $attachment_id->get_error_code(), 'error_description' => $attachment_id->get_error_message() ); |
3521
|
|
|
} else { |
3522
|
|
|
$attachment = get_post( $attachment_id ); |
3523
|
|
|
$uploaded_files[$index] = (object) array( |
3524
|
|
|
'id' => (string) $attachment_id, |
3525
|
|
|
'file' => $attachment->post_title, |
3526
|
|
|
'url' => wp_get_attachment_url( $attachment_id ), |
3527
|
|
|
'type' => $attachment->post_mime_type, |
3528
|
|
|
'meta' => wp_get_attachment_metadata( $attachment_id ), |
3529
|
|
|
); |
3530
|
|
|
} |
3531
|
|
|
} |
3532
|
|
|
if ( ! is_null( $global_post ) ) { |
3533
|
|
|
$GLOBALS['post'] = $global_post; |
3534
|
|
|
} |
3535
|
|
|
|
3536
|
|
|
return $uploaded_files; |
3537
|
|
|
} |
3538
|
|
|
|
3539
|
|
|
/** |
3540
|
|
|
* Add help to the Jetpack page |
3541
|
|
|
* |
3542
|
|
|
* @since Jetpack (1.2.3) |
3543
|
|
|
* @return false if not the Jetpack page |
3544
|
|
|
*/ |
3545
|
|
|
function admin_help() { |
3546
|
|
|
$current_screen = get_current_screen(); |
3547
|
|
|
|
3548
|
|
|
// Overview |
3549
|
|
|
$current_screen->add_help_tab( |
3550
|
|
|
array( |
3551
|
|
|
'id' => 'home', |
3552
|
|
|
'title' => __( 'Home', 'jetpack' ), |
3553
|
|
|
'content' => |
3554
|
|
|
'<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' . |
3555
|
|
|
'<p>' . __( 'Jetpack supercharges your self-hosted WordPress site with the awesome cloud power of WordPress.com.', 'jetpack' ) . '</p>' . |
3556
|
|
|
'<p>' . __( 'On this page, you are able to view the modules available within Jetpack, learn more about them, and activate or deactivate them as needed.', 'jetpack' ) . '</p>', |
3557
|
|
|
) |
3558
|
|
|
); |
3559
|
|
|
|
3560
|
|
|
// Screen Content |
3561
|
|
|
if ( current_user_can( 'manage_options' ) ) { |
3562
|
|
|
$current_screen->add_help_tab( |
3563
|
|
|
array( |
3564
|
|
|
'id' => 'settings', |
3565
|
|
|
'title' => __( 'Settings', 'jetpack' ), |
3566
|
|
|
'content' => |
3567
|
|
|
'<p><strong>' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</strong></p>' . |
3568
|
|
|
'<p>' . __( 'You can activate or deactivate individual Jetpack modules to suit your needs.', 'jetpack' ) . '</p>' . |
3569
|
|
|
'<ol>' . |
3570
|
|
|
'<li>' . __( 'Each module has an Activate or Deactivate link so you can toggle one individually.', 'jetpack' ) . '</li>' . |
3571
|
|
|
'<li>' . __( 'Using the checkboxes next to each module, you can select multiple modules to toggle via the Bulk Actions menu at the top of the list.', 'jetpack' ) . '</li>' . |
3572
|
|
|
'</ol>' . |
3573
|
|
|
'<p>' . __( 'Using the tools on the right, you can search for specific modules, filter by module categories or which are active, or change the sorting order.', 'jetpack' ) . '</p>' |
3574
|
|
|
) |
3575
|
|
|
); |
3576
|
|
|
} |
3577
|
|
|
|
3578
|
|
|
// Help Sidebar |
3579
|
|
|
$current_screen->set_help_sidebar( |
3580
|
|
|
'<p><strong>' . __( 'For more information:', 'jetpack' ) . '</strong></p>' . |
3581
|
|
|
'<p><a href="http://jetpack.me/faq/" target="_blank">' . __( 'Jetpack FAQ', 'jetpack' ) . '</a></p>' . |
3582
|
|
|
'<p><a href="http://jetpack.me/support/" target="_blank">' . __( 'Jetpack Support', 'jetpack' ) . '</a></p>' . |
3583
|
|
|
'<p><a href="' . Jetpack::admin_url( array( 'page' => 'jetpack-debugger' ) ) .'">' . __( 'Jetpack Debugging Center', 'jetpack' ) . '</a></p>' |
3584
|
|
|
); |
3585
|
|
|
} |
3586
|
|
|
|
3587
|
|
|
function admin_menu_css() { |
3588
|
|
|
wp_enqueue_style( 'jetpack-icons' ); |
3589
|
|
|
} |
3590
|
|
|
|
3591
|
|
|
function admin_menu_order() { |
3592
|
|
|
return true; |
3593
|
|
|
} |
3594
|
|
|
|
3595
|
|
View Code Duplication |
function jetpack_menu_order( $menu_order ) { |
3596
|
|
|
$jp_menu_order = array(); |
3597
|
|
|
|
3598
|
|
|
foreach ( $menu_order as $index => $item ) { |
3599
|
|
|
if ( $item != 'jetpack' ) { |
3600
|
|
|
$jp_menu_order[] = $item; |
3601
|
|
|
} |
3602
|
|
|
|
3603
|
|
|
if ( $index == 0 ) { |
3604
|
|
|
$jp_menu_order[] = 'jetpack'; |
3605
|
|
|
} |
3606
|
|
|
} |
3607
|
|
|
|
3608
|
|
|
return $jp_menu_order; |
3609
|
|
|
} |
3610
|
|
|
|
3611
|
|
|
function admin_head() { |
3612
|
|
View Code Duplication |
if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) ) |
3613
|
|
|
/** This action is documented in class.jetpack-admin-page.php */ |
3614
|
|
|
do_action( 'jetpack_module_configuration_head_' . $_GET['configure'] ); |
3615
|
|
|
} |
3616
|
|
|
|
3617
|
|
|
function admin_banner_styles() { |
3618
|
|
|
$min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min'; |
3619
|
|
|
|
3620
|
|
|
wp_enqueue_style( 'jetpack', plugins_url( "css/jetpack-banners{$min}.css", JETPACK__PLUGIN_FILE ), false, JETPACK__VERSION . '-20121016' ); |
3621
|
|
|
wp_style_add_data( 'jetpack', 'rtl', 'replace' ); |
3622
|
|
|
wp_style_add_data( 'jetpack', 'suffix', $min ); |
3623
|
|
|
} |
3624
|
|
|
|
3625
|
|
|
function admin_scripts() { |
3626
|
|
|
wp_enqueue_script( 'jetpack-js', plugins_url( '_inc/jp.js', JETPACK__PLUGIN_FILE ), array( 'jquery', 'wp-util' ), JETPACK__VERSION . '-20121111' ); |
3627
|
|
|
wp_localize_script( |
3628
|
|
|
'jetpack-js', |
3629
|
|
|
'jetpackL10n', |
3630
|
|
|
array( |
3631
|
|
|
'ays_disconnect' => "This will deactivate all Jetpack modules.\nAre you sure you want to disconnect?", |
3632
|
|
|
'ays_unlink' => "This will prevent user-specific modules such as Publicize, Notifications and Post By Email from working.\nAre you sure you want to unlink?", |
3633
|
|
|
'ays_dismiss' => "This will deactivate Jetpack.\nAre you sure you want to deactivate Jetpack?", |
3634
|
|
|
) |
3635
|
|
|
); |
3636
|
|
|
add_action( 'admin_footer', array( $this, 'do_stats' ) ); |
3637
|
|
|
} |
3638
|
|
|
|
3639
|
|
|
function plugin_action_links( $actions ) { |
3640
|
|
|
|
3641
|
|
|
$jetpack_home = array( 'jetpack-home' => sprintf( '<a href="%s">%s</a>', Jetpack::admin_url( 'page=jetpack' ), __( 'Jetpack', 'jetpack' ) ) ); |
3642
|
|
|
|
3643
|
|
|
if( current_user_can( 'jetpack_manage_modules' ) && ( Jetpack::is_active() || Jetpack::is_development_mode() ) ) { |
3644
|
|
|
return array_merge( |
3645
|
|
|
$jetpack_home, |
3646
|
|
|
array( 'settings' => sprintf( '<a href="%s">%s</a>', Jetpack::admin_url( 'page=jetpack_modules' ), __( 'Settings', 'jetpack' ) ) ), |
3647
|
|
|
array( 'support' => sprintf( '<a href="%s">%s</a>', Jetpack::admin_url( 'page=jetpack-debugger '), __( 'Support', 'jetpack' ) ) ), |
3648
|
|
|
$actions |
3649
|
|
|
); |
3650
|
|
|
} |
3651
|
|
|
|
3652
|
|
|
return array_merge( $jetpack_home, $actions ); |
3653
|
|
|
} |
3654
|
|
|
|
3655
|
|
|
function admin_connect_notice() { |
3656
|
|
|
// Don't show the connect notice anywhere but the plugins.php after activating |
3657
|
|
|
$current = get_current_screen(); |
3658
|
|
|
if ( 'plugins' !== $current->parent_base ) |
3659
|
|
|
return; |
3660
|
|
|
|
3661
|
|
|
if ( ! current_user_can( 'jetpack_connect' ) ) |
3662
|
|
|
return; |
3663
|
|
|
|
3664
|
|
|
$dismiss_and_deactivate_url = wp_nonce_url( Jetpack::admin_url( '?page=jetpack&jetpack-notice=dismiss' ), 'jetpack-deactivate' ); |
3665
|
|
|
?> |
3666
|
|
|
<div id="message" class="updated jetpack-message jp-banner" style="display:block !important;"> |
3667
|
|
|
<a class="jp-banner__dismiss" href="<?php echo esc_url( $dismiss_and_deactivate_url ); ?>" title="<?php esc_attr_e( 'Dismiss this notice and deactivate Jetpack.', 'jetpack' ); ?>"></a> |
3668
|
|
|
<?php if ( in_array( Jetpack_Options::get_option( 'activated' ) , array( 1, 2, 3 ) ) ) : ?> |
3669
|
|
|
<div class="jp-banner__content is-connection"> |
3670
|
|
|
<h2><?php _e( 'Your Jetpack is almost ready!', 'jetpack' ); ?></h2> |
3671
|
|
|
<p><?php _e( 'Connect now to enable features like Stats, Likes, and Social Sharing.', 'jetpack' ); ?></p> |
3672
|
|
|
</div> |
3673
|
|
|
<div class="jp-banner__action-container is-connection"> |
3674
|
|
|
<a href="<?php echo $this->build_connect_url() ?>" class="jp-banner__button" id="wpcom-connect"><?php _e( 'Connect to WordPress.com', 'jetpack' ); ?></a> |
3675
|
|
|
</div> |
3676
|
|
View Code Duplication |
<?php else : ?> |
3677
|
|
|
<div class="jp-banner__content"> |
3678
|
|
|
<h2><?php _e( 'Jetpack is installed!', 'jetpack' ) ?></h2> |
3679
|
|
|
<p><?php _e( 'It\'s ready to bring awesome, WordPress.com cloud-powered features to your site.', 'jetpack' ) ?></p> |
3680
|
|
|
</div> |
3681
|
|
|
<div class="jp-banner__action-container"> |
3682
|
|
|
<a href="<?php echo Jetpack::admin_url() ?>" class="jp-banner__button" id="wpcom-connect"><?php _e( 'Learn More', 'jetpack' ); ?></a> |
3683
|
|
|
</div> |
3684
|
|
|
<?php endif; ?> |
3685
|
|
|
</div> |
3686
|
|
|
|
3687
|
|
|
<?php |
3688
|
|
|
} |
3689
|
|
|
|
3690
|
|
|
/** |
3691
|
|
|
* This is the first banner |
3692
|
|
|
* It should be visible only to user that can update the option |
3693
|
|
|
* Are not connected |
3694
|
|
|
* |
3695
|
|
|
* @return null |
3696
|
|
|
*/ |
3697
|
|
|
function admin_jetpack_manage_notice() { |
3698
|
|
|
$screen = get_current_screen(); |
3699
|
|
|
|
3700
|
|
|
// Don't show the connect notice on the jetpack settings page. |
3701
|
|
|
if ( ! in_array( $screen->base, array( 'dashboard' ) ) || $screen->is_network || $screen->action ) |
3702
|
|
|
return; |
3703
|
|
|
|
3704
|
|
|
// Only show it if don't have the managment option set. |
3705
|
|
|
// And not dismissed it already. |
3706
|
|
|
if ( ! $this->can_display_jetpack_manage_notice() || Jetpack_Options::get_option( 'dismissed_manage_banner' ) ) { |
3707
|
|
|
return; |
3708
|
|
|
} |
3709
|
|
|
|
3710
|
|
|
$opt_out_url = $this->opt_out_jetpack_manage_url(); |
3711
|
|
|
$opt_in_url = $this->opt_in_jetpack_manage_url(); |
3712
|
|
|
/** |
3713
|
|
|
* I think it would be great to have different wordsing depending on where you are |
3714
|
|
|
* for example if we show the notice on dashboard and a different one if we show it on Plugins screen |
3715
|
|
|
* etc.. |
3716
|
|
|
*/ |
3717
|
|
|
|
3718
|
|
|
?> |
3719
|
|
|
<div id="message" class="updated jetpack-message jp-banner is-opt-in" style="display:block !important;"> |
3720
|
|
|
<a class="jp-banner__dismiss" href="<?php echo esc_url( $opt_out_url ); ?>" title="<?php esc_attr_e( 'Dismiss this notice for now.', 'jetpack' ); ?>"></a> |
3721
|
|
|
<div class="jp-banner__content"> |
3722
|
|
|
<h2><?php esc_html_e( 'New in Jetpack: Centralized Site Management', 'jetpack' ); ?></h2> |
3723
|
|
|
<p><?php printf( __( 'Manage multiple sites from one dashboard at wordpress.com/sites. Enabling allows all existing, connected Administrators to modify your site from WordPress.com. <a href="%s" target="_blank">Learn More</a>.', 'jetpack' ), 'http://jetpack.me/support/site-management' ); ?></p> |
3724
|
|
|
</div> |
3725
|
|
|
<div class="jp-banner__action-container is-opt-in"> |
3726
|
|
|
<a href="<?php echo esc_url( $opt_in_url ); ?>" class="jp-banner__button" id="wpcom-connect"><?php _e( 'Activate now', 'jetpack' ); ?></a> |
3727
|
|
|
</div> |
3728
|
|
|
</div> |
3729
|
|
|
<?php |
3730
|
|
|
} |
3731
|
|
|
|
3732
|
|
|
/** |
3733
|
|
|
* Returns the url that the user clicks to remove the notice for the big banner |
3734
|
|
|
* @return (string) |
3735
|
|
|
*/ |
3736
|
|
|
function opt_out_jetpack_manage_url() { |
3737
|
|
|
$referer = '&_wp_http_referer=' . add_query_arg( '_wp_http_referer', null ); |
3738
|
|
|
return wp_nonce_url( Jetpack::admin_url( 'jetpack-notice=jetpack-manage-opt-out' . $referer ), 'jetpack_manage_banner_opt_out' ); |
3739
|
|
|
} |
3740
|
|
|
/** |
3741
|
|
|
* Returns the url that the user clicks to opt in to Jetpack Manage |
3742
|
|
|
* @return (string) |
3743
|
|
|
*/ |
3744
|
|
|
function opt_in_jetpack_manage_url() { |
3745
|
|
|
return wp_nonce_url( Jetpack::admin_url( 'jetpack-notice=jetpack-manage-opt-in' ), 'jetpack_manage_banner_opt_in' ); |
3746
|
|
|
} |
3747
|
|
|
|
3748
|
|
|
function opt_in_jetpack_manage_notice() { |
3749
|
|
|
?> |
3750
|
|
|
<div class="wrap"> |
3751
|
|
|
<div id="message" class="jetpack-message is-opt-in"> |
3752
|
|
|
<?php echo sprintf( __( '<p><a href="%1$s" title="Opt in to WordPress.com Site Management" >Activate Site Management</a> to manage multiple sites from our centralized dashboard at wordpress.com/sites. <a href="%2$s" target="_blank">Learn more</a>.</p><a href="%1$s" class="jp-button">Activate Now</a>', 'jetpack' ), $this->opt_in_jetpack_manage_url(), 'http://jetpack.me/support/site-management' ); ?> |
3753
|
|
|
</div> |
3754
|
|
|
</div> |
3755
|
|
|
<?php |
3756
|
|
|
|
3757
|
|
|
} |
3758
|
|
|
/** |
3759
|
|
|
* Determines whether to show the notice of not true = display notice |
3760
|
|
|
* @return (bool) |
3761
|
|
|
*/ |
3762
|
|
|
function can_display_jetpack_manage_notice() { |
3763
|
|
|
// never display the notice to users that can't do anything about it anyways |
3764
|
|
|
if( ! current_user_can( 'jetpack_manage_modules' ) ) |
3765
|
|
|
return false; |
3766
|
|
|
|
3767
|
|
|
// don't display if we are in development more |
3768
|
|
|
if( Jetpack::is_development_mode() ) { |
3769
|
|
|
return false; |
3770
|
|
|
} |
3771
|
|
|
// don't display if the site is private |
3772
|
|
|
if( ! Jetpack_Options::get_option( 'public' ) ) |
3773
|
|
|
return false; |
3774
|
|
|
|
3775
|
|
|
/** |
3776
|
|
|
* Should the Jetpack Remote Site Management notice be displayed. |
3777
|
|
|
* |
3778
|
|
|
* @since 3.3.0 |
3779
|
|
|
* |
3780
|
|
|
* @param bool ! self::is_module_active( 'manage' ) Is the Manage module inactive. |
3781
|
|
|
*/ |
3782
|
|
|
return apply_filters( 'can_display_jetpack_manage_notice', ! self::is_module_active( 'manage' ) ); |
3783
|
|
|
} |
3784
|
|
|
|
3785
|
|
|
function network_connect_notice() { |
3786
|
|
|
?> |
3787
|
|
|
<div id="message" class="updated jetpack-message"> |
3788
|
|
|
<div class="squeezer"> |
3789
|
|
|
<h2><?php _e( '<strong>Jetpack is activated!</strong> Each site on your network must be connected individually by an admin on that site.', 'jetpack' ) ?></h2> |
3790
|
|
|
</div> |
3791
|
|
|
</div> |
3792
|
|
|
<?php |
3793
|
|
|
} |
3794
|
|
|
|
3795
|
|
|
public static function jetpack_comment_notice() { |
3796
|
|
|
if ( in_array( 'comments', Jetpack::get_active_modules() ) ) { |
3797
|
|
|
return ''; |
3798
|
|
|
} |
3799
|
|
|
|
3800
|
|
|
$jetpack_old_version = explode( ':', Jetpack_Options::get_option( 'old_version' ) ); |
3801
|
|
|
$jetpack_new_version = explode( ':', Jetpack_Options::get_option( 'version' ) ); |
3802
|
|
|
|
3803
|
|
|
if ( $jetpack_old_version ) { |
|
|
|
|
3804
|
|
|
if ( version_compare( $jetpack_old_version[0], '1.4', '>=' ) ) { |
3805
|
|
|
return ''; |
3806
|
|
|
} |
3807
|
|
|
} |
3808
|
|
|
|
3809
|
|
|
if ( $jetpack_new_version ) { |
|
|
|
|
3810
|
|
|
if ( version_compare( $jetpack_new_version[0], '1.4-something', '<' ) ) { |
3811
|
|
|
return ''; |
3812
|
|
|
} |
3813
|
|
|
} |
3814
|
|
|
|
3815
|
|
|
return '<br /><br />' . sprintf( |
3816
|
|
|
__( 'Jetpack now includes Comments, which enables your visitors to use their WordPress.com, Twitter, or Facebook accounts when commenting on your site. To activate Comments, <a href="%s">%s</a>.', 'jetpack' ), |
3817
|
|
|
wp_nonce_url( |
3818
|
|
|
Jetpack::admin_url( |
3819
|
|
|
array( |
3820
|
|
|
'page' => 'jetpack', |
3821
|
|
|
'action' => 'activate', |
3822
|
|
|
'module' => 'comments', |
3823
|
|
|
) |
3824
|
|
|
), |
3825
|
|
|
'jetpack_activate-comments' |
3826
|
|
|
), |
3827
|
|
|
__( 'click here', 'jetpack' ) |
3828
|
|
|
); |
3829
|
|
|
} |
3830
|
|
|
|
3831
|
|
|
/** |
3832
|
|
|
* Show the survey link when the user has just disconnected Jetpack. |
3833
|
|
|
*/ |
3834
|
|
|
function disconnect_survey_notice() { |
3835
|
|
|
?> |
3836
|
|
|
<div class="wrap"> |
3837
|
|
|
<div id="message" class="jetpack-message stay-visible"> |
3838
|
|
|
<div class="squeezer"> |
3839
|
|
|
<h2> |
3840
|
|
|
<?php _e( 'You have successfully disconnected Jetpack.', 'jetpack' ); ?> |
3841
|
|
|
<br /> |
3842
|
|
|
<?php echo sprintf( |
3843
|
|
|
__( 'Would you tell us why? Just <a href="%1$s" target="%2$s">answering two simple questions</a> would help us improve Jetpack.', 'jetpack' ), |
3844
|
|
|
'https://jetpack.me/survey-disconnected/', |
3845
|
|
|
'_blank' |
3846
|
|
|
); ?> |
3847
|
|
|
</h2> |
3848
|
|
|
</div> |
3849
|
|
|
</div> |
3850
|
|
|
</div> |
3851
|
|
|
<?php |
3852
|
|
|
} |
3853
|
|
|
|
3854
|
|
|
/* |
3855
|
|
|
* Registration flow: |
3856
|
|
|
* 1 - ::admin_page_load() action=register |
3857
|
|
|
* 2 - ::try_registration() |
3858
|
|
|
* 3 - ::register() |
3859
|
|
|
* - Creates jetpack_register option containing two secrets and a timestamp |
3860
|
|
|
* - Calls https://jetpack.wordpress.com/jetpack.register/1/ with |
3861
|
|
|
* siteurl, home, gmt_offset, timezone_string, site_name, secret_1, secret_2, site_lang, timeout, stats_id |
3862
|
|
|
* - That request to jetpack.wordpress.com does not immediately respond. It first makes a request BACK to this site's |
3863
|
|
|
* xmlrpc.php?for=jetpack: RPC method: jetpack.verifyRegistration, Parameters: secret_1 |
3864
|
|
|
* - The XML-RPC request verifies secret_1, deletes both secrets and responds with: secret_2 |
3865
|
|
|
* - https://jetpack.wordpress.com/jetpack.register/1/ verifies that XML-RPC response (secret_2) then finally responds itself with |
3866
|
|
|
* jetpack_id, jetpack_secret, jetpack_public |
3867
|
|
|
* - ::register() then stores jetpack_options: id => jetpack_id, blog_token => jetpack_secret |
3868
|
|
|
* 4 - redirect to https://jetpack.wordpress.com/jetpack.authorize/1/ |
3869
|
|
|
* 5 - user logs in with WP.com account |
3870
|
|
|
* 6 - redirect to this site's wp-admin/index.php?page=jetpack&action=authorize with |
3871
|
|
|
* code <-- OAuth2 style authorization code |
3872
|
|
|
* 7 - ::admin_page_load() action=authorize |
3873
|
|
|
* 8 - Jetpack_Client_Server::authorize() |
3874
|
|
|
* 9 - Jetpack_Client_Server::get_token() |
3875
|
|
|
* 10- GET https://jetpack.wordpress.com/jetpack.token/1/ with |
3876
|
|
|
* client_id, client_secret, grant_type, code, redirect_uri:action=authorize, state, scope, user_email, user_login |
3877
|
|
|
* 11- which responds with |
3878
|
|
|
* access_token, token_type, scope |
3879
|
|
|
* 12- Jetpack_Client_Server::authorize() stores jetpack_options: user_token => access_token.$user_id |
3880
|
|
|
* 13- Jetpack::activate_default_modules() |
3881
|
|
|
* Deactivates deprecated plugins |
3882
|
|
|
* Activates all default modules |
3883
|
|
|
* Catches errors: redirects to wp-admin/index.php?page=jetpack state:error=something |
3884
|
|
|
* 14- redirect to this site's wp-admin/index.php?page=jetpack with state:message=authorized |
3885
|
|
|
* Done! |
3886
|
|
|
*/ |
3887
|
|
|
|
3888
|
|
|
/** |
3889
|
|
|
* Handles the page load events for the Jetpack admin page |
3890
|
|
|
*/ |
3891
|
|
|
function admin_page_load() { |
3892
|
|
|
$error = false; |
3893
|
|
|
|
3894
|
|
|
// Make sure we have the right body class to hook stylings for subpages off of. |
3895
|
|
|
add_filter( 'admin_body_class', array( __CLASS__, 'add_jetpack_pagestyles' ) ); |
3896
|
|
|
|
3897
|
|
|
if ( ! empty( $_GET['jetpack_restate'] ) ) { |
3898
|
|
|
// Should only be used in intermediate redirects to preserve state across redirects |
3899
|
|
|
Jetpack::restate(); |
3900
|
|
|
} |
3901
|
|
|
|
3902
|
|
|
if ( isset( $_GET['connect_url_redirect'] ) ) { |
3903
|
|
|
// User clicked in the iframe to link their accounts |
3904
|
|
|
if ( ! Jetpack::is_user_connected() ) { |
3905
|
|
|
$connect_url = $this->build_connect_url( true ); |
3906
|
|
|
if ( isset( $_GET['notes_iframe'] ) ) |
3907
|
|
|
$connect_url .= '¬es_iframe'; |
3908
|
|
|
wp_redirect( $connect_url ); |
3909
|
|
|
exit; |
|
|
|
|
3910
|
|
|
} else { |
3911
|
|
|
Jetpack::state( 'message', 'already_authorized' ); |
3912
|
|
|
wp_safe_redirect( Jetpack::admin_url() ); |
3913
|
|
|
exit; |
|
|
|
|
3914
|
|
|
} |
3915
|
|
|
} |
3916
|
|
|
|
3917
|
|
|
|
3918
|
|
|
if ( isset( $_GET['action'] ) ) { |
3919
|
|
|
switch ( $_GET['action'] ) { |
3920
|
|
|
case 'authorize' : |
3921
|
|
|
if ( Jetpack::is_active() && Jetpack::is_user_connected() ) { |
3922
|
|
|
Jetpack::state( 'message', 'already_authorized' ); |
3923
|
|
|
wp_safe_redirect( Jetpack::admin_url() ); |
3924
|
|
|
exit; |
|
|
|
|
3925
|
|
|
} |
3926
|
|
|
Jetpack::log( 'authorize' ); |
3927
|
|
|
$client_server = new Jetpack_Client_Server; |
3928
|
|
|
$client_server->authorize(); |
3929
|
|
|
exit; |
|
|
|
|
3930
|
|
|
case 'register' : |
3931
|
|
|
if ( ! current_user_can( 'jetpack_connect' ) ) { |
3932
|
|
|
$error = 'cheatin'; |
3933
|
|
|
break; |
3934
|
|
|
} |
3935
|
|
|
check_admin_referer( 'jetpack-register' ); |
3936
|
|
|
Jetpack::log( 'register' ); |
3937
|
|
|
Jetpack::maybe_set_version_option(); |
3938
|
|
|
$registered = Jetpack::try_registration(); |
3939
|
|
|
if ( is_wp_error( $registered ) ) { |
3940
|
|
|
$error = $registered->get_error_code(); |
3941
|
|
|
Jetpack::state( 'error_description', $registered->get_error_message() ); |
3942
|
|
|
break; |
3943
|
|
|
} |
3944
|
|
|
|
3945
|
|
|
wp_redirect( $this->build_connect_url( true ) ); |
3946
|
|
|
exit; |
|
|
|
|
3947
|
|
|
case 'activate' : |
3948
|
|
|
if ( ! current_user_can( 'jetpack_activate_modules' ) ) { |
3949
|
|
|
$error = 'cheatin'; |
3950
|
|
|
break; |
3951
|
|
|
} |
3952
|
|
|
|
3953
|
|
|
$module = stripslashes( $_GET['module'] ); |
3954
|
|
|
check_admin_referer( "jetpack_activate-$module" ); |
3955
|
|
|
Jetpack::log( 'activate', $module ); |
3956
|
|
|
Jetpack::activate_module( $module ); |
3957
|
|
|
// The following two lines will rarely happen, as Jetpack::activate_module normally exits at the end. |
3958
|
|
|
wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) ); |
3959
|
|
|
exit; |
|
|
|
|
3960
|
|
|
case 'activate_default_modules' : |
3961
|
|
|
check_admin_referer( 'activate_default_modules' ); |
3962
|
|
|
Jetpack::log( 'activate_default_modules' ); |
3963
|
|
|
Jetpack::restate(); |
3964
|
|
|
$min_version = isset( $_GET['min_version'] ) ? $_GET['min_version'] : false; |
3965
|
|
|
$max_version = isset( $_GET['max_version'] ) ? $_GET['max_version'] : false; |
3966
|
|
|
$other_modules = isset( $_GET['other_modules'] ) && is_array( $_GET['other_modules'] ) ? $_GET['other_modules'] : array(); |
3967
|
|
|
Jetpack::activate_default_modules( $min_version, $max_version, $other_modules ); |
3968
|
|
|
wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) ); |
3969
|
|
|
exit; |
|
|
|
|
3970
|
|
|
case 'disconnect' : |
3971
|
|
|
if ( ! current_user_can( 'jetpack_disconnect' ) ) { |
3972
|
|
|
$error = 'cheatin'; |
3973
|
|
|
break; |
3974
|
|
|
} |
3975
|
|
|
|
3976
|
|
|
check_admin_referer( 'jetpack-disconnect' ); |
3977
|
|
|
Jetpack::log( 'disconnect' ); |
3978
|
|
|
Jetpack::disconnect(); |
3979
|
|
|
wp_safe_redirect( Jetpack::admin_url( 'disconnected=true' ) ); |
3980
|
|
|
exit; |
|
|
|
|
3981
|
|
|
case 'reconnect' : |
3982
|
|
|
if ( ! current_user_can( 'jetpack_reconnect' ) ) { |
3983
|
|
|
$error = 'cheatin'; |
3984
|
|
|
break; |
3985
|
|
|
} |
3986
|
|
|
|
3987
|
|
|
check_admin_referer( 'jetpack-reconnect' ); |
3988
|
|
|
Jetpack::log( 'reconnect' ); |
3989
|
|
|
$this->disconnect(); |
3990
|
|
|
wp_redirect( $this->build_connect_url( true ) ); |
3991
|
|
|
exit; |
|
|
|
|
3992
|
|
View Code Duplication |
case 'deactivate' : |
3993
|
|
|
if ( ! current_user_can( 'jetpack_deactivate_modules' ) ) { |
3994
|
|
|
$error = 'cheatin'; |
3995
|
|
|
break; |
3996
|
|
|
} |
3997
|
|
|
|
3998
|
|
|
$modules = stripslashes( $_GET['module'] ); |
3999
|
|
|
check_admin_referer( "jetpack_deactivate-$modules" ); |
4000
|
|
|
foreach ( explode( ',', $modules ) as $module ) { |
4001
|
|
|
Jetpack::log( 'deactivate', $module ); |
4002
|
|
|
Jetpack::deactivate_module( $module ); |
4003
|
|
|
Jetpack::state( 'message', 'module_deactivated' ); |
4004
|
|
|
} |
4005
|
|
|
Jetpack::state( 'module', $modules ); |
4006
|
|
|
wp_safe_redirect( Jetpack::admin_url( 'page=jetpack' ) ); |
4007
|
|
|
exit; |
|
|
|
|
4008
|
|
|
case 'unlink' : |
4009
|
|
|
$redirect = isset( $_GET['redirect'] ) ? $_GET['redirect'] : ''; |
4010
|
|
|
check_admin_referer( 'jetpack-unlink' ); |
4011
|
|
|
Jetpack::log( 'unlink' ); |
4012
|
|
|
$this->unlink_user(); |
4013
|
|
|
Jetpack::state( 'message', 'unlinked' ); |
4014
|
|
|
if ( 'sub-unlink' == $redirect ) { |
4015
|
|
|
wp_safe_redirect( admin_url() ); |
4016
|
|
|
} else { |
4017
|
|
|
wp_safe_redirect( Jetpack::admin_url( array( 'page' => $redirect ) ) ); |
4018
|
|
|
} |
4019
|
|
|
exit; |
|
|
|
|
4020
|
|
|
default: |
4021
|
|
|
/** |
4022
|
|
|
* Fires when a Jetpack admin page is loaded with an unrecognized parameter. |
4023
|
|
|
* |
4024
|
|
|
* @since 2.6.0 |
4025
|
|
|
* |
4026
|
|
|
* @param string sanitize_key( $_GET['action'] ) Unrecognized URL parameter. |
4027
|
|
|
*/ |
4028
|
|
|
do_action( 'jetpack_unrecognized_action', sanitize_key( $_GET['action'] ) ); |
4029
|
|
|
} |
4030
|
|
|
} |
4031
|
|
|
|
4032
|
|
|
if ( ! $error = $error ? $error : Jetpack::state( 'error' ) ) { |
4033
|
|
|
self::activate_new_modules( true ); |
4034
|
|
|
} |
4035
|
|
|
|
4036
|
|
|
switch ( $error ) { |
4037
|
|
|
case 'cheatin' : |
4038
|
|
|
$this->error = __( 'Cheatin’ uh?', 'jetpack' ); |
4039
|
|
|
break; |
4040
|
|
|
case 'access_denied' : |
4041
|
|
|
$this->error = __( 'You need to authorize the Jetpack connection between your site and WordPress.com to enable the awesome features.', 'jetpack' ); |
4042
|
|
|
break; |
4043
|
|
|
case 'wrong_state' : |
4044
|
|
|
$this->error = __( 'Don’t cross the streams! You need to stay logged in to your WordPress blog while you authorize Jetpack.', 'jetpack' ); |
4045
|
|
|
break; |
4046
|
|
|
case 'invalid_client' : |
4047
|
|
|
// @todo re-register instead of deactivate/reactivate |
|
|
|
|
4048
|
|
|
$this->error = __( 'Return to sender. Whoops! It looks like you got the wrong Jetpack in the mail; deactivate then reactivate the Jetpack plugin to get a new one.', 'jetpack' ); |
4049
|
|
|
break; |
4050
|
|
|
case 'invalid_grant' : |
4051
|
|
|
$this->error = __( 'Wrong size. Hm… it seems your Jetpack doesn’t quite fit. Have you lost weight? Click “Connect to WordPress.com” again to get your Jetpack adjusted.', 'jetpack' ); |
4052
|
|
|
break; |
4053
|
|
|
case 'site_inaccessible' : |
4054
|
|
|
case 'site_requires_authorization' : |
4055
|
|
|
$this->error = sprintf( __( 'Your website needs to be publicly accessible to use Jetpack: %s', 'jetpack' ), "<code>$error</code>" ); |
4056
|
|
|
break; |
4057
|
|
|
case 'module_activation_failed' : |
4058
|
|
|
$module = Jetpack::state( 'module' ); |
4059
|
|
|
if ( ! empty( $module ) && $mod = Jetpack::get_module( $module ) ) { |
4060
|
|
|
$this->error = sprintf( __( '%s could not be activated because it triggered a <strong>fatal error</strong>. Perhaps there is a conflict with another plugin you have installed?', 'jetpack' ), $mod['name'] ); |
4061
|
|
|
if ( isset( $this->plugins_to_deactivate[$module] ) ) { |
4062
|
|
|
$this->error .= ' ' . sprintf( __( 'Do you still have the %s plugin installed?', 'jetpack' ), $this->plugins_to_deactivate[$module][1] ); |
4063
|
|
|
} |
4064
|
|
|
} else { |
4065
|
|
|
$this->error = __( 'Module could not be activated because it triggered a <strong>fatal error</strong>. Perhaps there is a conflict with another plugin you have installed?', 'jetpack' ); |
4066
|
|
|
} |
4067
|
|
|
if ( $php_errors = Jetpack::state( 'php_errors' ) ) { |
4068
|
|
|
$this->error .= "<br />\n"; |
4069
|
|
|
$this->error .= $php_errors; |
4070
|
|
|
} |
4071
|
|
|
break; |
4072
|
|
|
case 'master_user_required' : |
4073
|
|
|
$module = Jetpack::state( 'module' ); |
4074
|
|
|
$module_name = ''; |
4075
|
|
|
if ( ! empty( $module ) && $mod = Jetpack::get_module( $module ) ) { |
4076
|
|
|
$module_name = $mod['name']; |
4077
|
|
|
} |
4078
|
|
|
|
4079
|
|
|
$master_user = Jetpack_Options::get_option( 'master_user' ); |
4080
|
|
|
$master_userdata = get_userdata( $master_user ) ; |
4081
|
|
|
if ( $master_userdata ) { |
4082
|
|
|
if ( ! in_array( $module, Jetpack::get_active_modules() ) ) { |
4083
|
|
|
$this->error = sprintf( __( '%s was not activated.' , 'jetpack' ), $module_name ); |
4084
|
|
|
} else { |
4085
|
|
|
$this->error = sprintf( __( '%s was not deactivated.' , 'jetpack' ), $module_name ); |
4086
|
|
|
} |
4087
|
|
|
$this->error .= ' ' . sprintf( __( 'This module can only be altered by %s, the user who initiated the Jetpack connection on this site.' , 'jetpack' ), esc_html( $master_userdata->display_name ) ); |
4088
|
|
|
|
4089
|
|
|
} else { |
4090
|
|
|
$this->error = sprintf( __( 'Only the user who initiated the Jetpack connection on this site can toggle %s, but that user no longer exists. This should not happen.', 'jetpack' ), $module_name ); |
4091
|
|
|
} |
4092
|
|
|
break; |
4093
|
|
|
case 'not_public' : |
4094
|
|
|
$this->error = __( '<strong>Your Jetpack has a glitch.</strong> Connecting this site with WordPress.com is not possible. This usually means your site is not publicly accessible (localhost).', 'jetpack' ); |
4095
|
|
|
break; |
4096
|
|
|
case 'wpcom_408' : |
4097
|
|
|
case 'wpcom_5??' : |
4098
|
|
|
case 'wpcom_bad_response' : |
4099
|
|
|
case 'wpcom_outage' : |
4100
|
|
|
$this->error = __( 'WordPress.com is currently having problems and is unable to fuel up your Jetpack. Please try again later.', 'jetpack' ); |
4101
|
|
|
break; |
4102
|
|
|
case 'register_http_request_failed' : |
4103
|
|
|
case 'token_http_request_failed' : |
4104
|
|
|
$this->error = sprintf( __( 'Jetpack could not contact WordPress.com: %s. This usually means something is incorrectly configured on your web host.', 'jetpack' ), "<code>$error</code>" ); |
4105
|
|
|
break; |
4106
|
|
|
default : |
|
|
|
|
4107
|
|
|
if ( empty( $error ) ) { |
4108
|
|
|
break; |
4109
|
|
|
} |
4110
|
|
|
$error = trim( substr( strip_tags( $error ), 0, 20 ) ); |
4111
|
|
|
// no break: fall through |
4112
|
|
|
case 'no_role' : |
|
|
|
|
4113
|
|
|
case 'no_cap' : |
4114
|
|
|
case 'no_code' : |
4115
|
|
|
case 'no_state' : |
4116
|
|
|
case 'invalid_state' : |
4117
|
|
|
case 'invalid_request' : |
4118
|
|
|
case 'invalid_scope' : |
4119
|
|
|
case 'unsupported_response_type' : |
4120
|
|
|
case 'invalid_token' : |
4121
|
|
|
case 'no_token' : |
4122
|
|
|
case 'missing_secrets' : |
4123
|
|
|
case 'home_missing' : |
4124
|
|
|
case 'siteurl_missing' : |
4125
|
|
|
case 'gmt_offset_missing' : |
4126
|
|
|
case 'site_name_missing' : |
4127
|
|
|
case 'secret_1_missing' : |
4128
|
|
|
case 'secret_2_missing' : |
4129
|
|
|
case 'site_lang_missing' : |
4130
|
|
|
case 'home_malformed' : |
4131
|
|
|
case 'siteurl_malformed' : |
4132
|
|
|
case 'gmt_offset_malformed' : |
4133
|
|
|
case 'timezone_string_malformed' : |
4134
|
|
|
case 'site_name_malformed' : |
4135
|
|
|
case 'secret_1_malformed' : |
4136
|
|
|
case 'secret_2_malformed' : |
4137
|
|
|
case 'site_lang_malformed' : |
4138
|
|
|
case 'secrets_mismatch' : |
4139
|
|
|
case 'verify_secret_1_missing' : |
4140
|
|
|
case 'verify_secret_1_malformed' : |
4141
|
|
|
case 'verify_secrets_missing' : |
4142
|
|
|
case 'verify_secrets_mismatch' : |
4143
|
|
|
$error = esc_html( $error ); |
4144
|
|
|
$this->error = sprintf( __( '<strong>Your Jetpack has a glitch.</strong> We’re sorry for the inconvenience. Please try again later, if the issue continues please contact support with this message: %s', 'jetpack' ), "<code>$error</code>" ); |
4145
|
|
|
if ( ! Jetpack::is_active() ) { |
4146
|
|
|
$this->error .= '<br />'; |
4147
|
|
|
$this->error .= sprintf( __( 'Try connecting again.', 'jetpack' ) ); |
4148
|
|
|
} |
4149
|
|
|
break; |
4150
|
|
|
} |
4151
|
|
|
|
4152
|
|
|
$message_code = Jetpack::state( 'message' ); |
4153
|
|
|
|
4154
|
|
|
$active_state = Jetpack::state( 'activated_modules' ); |
4155
|
|
|
if ( ! empty( $active_state ) ) { |
4156
|
|
|
$available = Jetpack::get_available_modules(); |
4157
|
|
|
$active_state = explode( ',', $active_state ); |
4158
|
|
|
$active_state = array_intersect( $active_state, $available ); |
4159
|
|
|
if ( count( $active_state ) ) { |
4160
|
|
|
foreach ( $active_state as $mod ) { |
4161
|
|
|
$this->stat( 'module-activated', $mod ); |
4162
|
|
|
} |
4163
|
|
|
} else { |
4164
|
|
|
$active_state = false; |
4165
|
|
|
} |
4166
|
|
|
} |
4167
|
|
|
if( Jetpack::state( 'optin-manage' ) ) { |
4168
|
|
|
$activated_manage = $message_code; |
4169
|
|
|
$message_code = 'jetpack-manage'; |
4170
|
|
|
|
4171
|
|
|
} |
4172
|
|
|
switch ( $message_code ) { |
4173
|
|
|
case 'modules_activated' : |
4174
|
|
|
$this->message = sprintf( |
4175
|
|
|
__( 'Welcome to <strong>Jetpack %s</strong>!', 'jetpack' ), |
4176
|
|
|
JETPACK__VERSION |
4177
|
|
|
); |
4178
|
|
|
|
4179
|
|
|
if ( $active_state ) { |
4180
|
|
|
$titles = array(); |
4181
|
|
View Code Duplication |
foreach ( $active_state as $mod ) { |
4182
|
|
|
if ( $mod_headers = Jetpack::get_module( $mod ) ) { |
4183
|
|
|
$titles[] = '<strong>' . preg_replace( '/\s+(?![^<>]++>)/', ' ', $mod_headers['name'] ) . '</strong>'; |
4184
|
|
|
} |
4185
|
|
|
} |
4186
|
|
|
if ( $titles ) { |
|
|
|
|
4187
|
|
|
$this->message .= '<br /><br />' . wp_sprintf( __( 'The following new modules have been activated: %l.', 'jetpack' ), $titles ); |
4188
|
|
|
} |
4189
|
|
|
} |
4190
|
|
|
|
4191
|
|
|
if ( $reactive_state = Jetpack::state( 'reactivated_modules' ) ) { |
4192
|
|
|
$titles = array(); |
4193
|
|
View Code Duplication |
foreach ( explode( ',', $reactive_state ) as $mod ) { |
4194
|
|
|
if ( $mod_headers = Jetpack::get_module( $mod ) ) { |
4195
|
|
|
$titles[] = '<strong>' . preg_replace( '/\s+(?![^<>]++>)/', ' ', $mod_headers['name'] ) . '</strong>'; |
4196
|
|
|
} |
4197
|
|
|
} |
4198
|
|
|
if ( $titles ) { |
|
|
|
|
4199
|
|
|
$this->message .= '<br /><br />' . wp_sprintf( __( 'The following modules have been updated: %l.', 'jetpack' ), $titles ); |
4200
|
|
|
} |
4201
|
|
|
} |
4202
|
|
|
|
4203
|
|
|
$this->message .= Jetpack::jetpack_comment_notice(); |
4204
|
|
|
break; |
4205
|
|
|
case 'jetpack-manage': |
4206
|
|
|
$this->message = '<strong>' . sprintf( __( 'You are all set! Your site can now be managed from <a href="%s" target="_blank">wordpress.com/sites</a>.', 'jetpack' ), 'https://wordpress.com/sites' ) . '</strong>'; |
4207
|
|
|
if ( $activated_manage ) { |
|
|
|
|
4208
|
|
|
$this->message .= '<br /><strong>' . __( 'Manage has been activated for you!', 'jetpack' ) . '</strong>'; |
4209
|
|
|
} |
4210
|
|
|
break; |
4211
|
|
|
case 'module_activated' : |
4212
|
|
|
if ( $module = Jetpack::get_module( Jetpack::state( 'module' ) ) ) { |
4213
|
|
|
$this->message = sprintf( __( '<strong>%s Activated!</strong> You can deactivate at any time by clicking the Deactivate link next to each module.', 'jetpack' ), $module['name'] ); |
4214
|
|
|
$this->stat( 'module-activated', Jetpack::state( 'module' ) ); |
4215
|
|
|
} |
4216
|
|
|
break; |
4217
|
|
|
|
4218
|
|
|
case 'module_deactivated' : |
4219
|
|
|
$modules = Jetpack::state( 'module' ); |
4220
|
|
|
if ( ! $modules ) { |
4221
|
|
|
break; |
4222
|
|
|
} |
4223
|
|
|
|
4224
|
|
|
$module_names = array(); |
4225
|
|
|
foreach ( explode( ',', $modules ) as $module_slug ) { |
4226
|
|
|
$module = Jetpack::get_module( $module_slug ); |
4227
|
|
|
if ( $module ) { |
4228
|
|
|
$module_names[] = $module['name']; |
4229
|
|
|
} |
4230
|
|
|
|
4231
|
|
|
$this->stat( 'module-deactivated', $module_slug ); |
4232
|
|
|
} |
4233
|
|
|
|
4234
|
|
|
if ( ! $module_names ) { |
|
|
|
|
4235
|
|
|
break; |
4236
|
|
|
} |
4237
|
|
|
|
4238
|
|
|
$this->message = wp_sprintf( |
4239
|
|
|
_nx( |
4240
|
|
|
'<strong>%l Deactivated!</strong> You can activate it again at any time using the activate link next to each module.', |
4241
|
|
|
'<strong>%l Deactivated!</strong> You can activate them again at any time using the activate links next to each module.', |
4242
|
|
|
count( $module_names ), |
4243
|
|
|
'%l = list of Jetpack module/feature names', |
4244
|
|
|
'jetpack' |
4245
|
|
|
), |
4246
|
|
|
$module_names |
4247
|
|
|
); |
4248
|
|
|
break; |
4249
|
|
|
|
4250
|
|
|
case 'module_configured' : |
4251
|
|
|
$this->message = __( '<strong>Module settings were saved.</strong> ', 'jetpack' ); |
4252
|
|
|
break; |
4253
|
|
|
|
4254
|
|
|
case 'already_authorized' : |
4255
|
|
|
$this->message = __( '<strong>Your Jetpack is already connected.</strong> ', 'jetpack' ); |
4256
|
|
|
break; |
4257
|
|
|
|
4258
|
|
|
case 'authorized' : |
4259
|
|
|
$this->message = __( '<strong>You’re fueled up and ready to go, Jetpack is now active.</strong> ', 'jetpack' ); |
4260
|
|
|
$this->message .= Jetpack::jetpack_comment_notice(); |
4261
|
|
|
break; |
4262
|
|
|
|
4263
|
|
|
case 'linked' : |
4264
|
|
|
$this->message = __( '<strong>You’re fueled up and ready to go.</strong> ', 'jetpack' ); |
4265
|
|
|
$this->message .= Jetpack::jetpack_comment_notice(); |
4266
|
|
|
break; |
4267
|
|
|
|
4268
|
|
|
case 'unlinked' : |
4269
|
|
|
$user = wp_get_current_user(); |
4270
|
|
|
$this->message = sprintf( __( '<strong>You have unlinked your account (%s) from WordPress.com.</strong>', 'jetpack' ), $user->user_login ); |
4271
|
|
|
break; |
4272
|
|
|
|
4273
|
|
|
case 'switch_master' : |
4274
|
|
|
global $current_user; |
4275
|
|
|
$is_master_user = $current_user->ID == Jetpack_Options::get_option( 'master_user' ); |
4276
|
|
|
$master_userdata = get_userdata( Jetpack_Options::get_option( 'master_user' ) ); |
4277
|
|
|
if ( $is_master_user ) { |
4278
|
|
|
$this->message = __( 'You have successfully set yourself as Jetpack’s primary user.', 'jetpack' ); |
4279
|
|
|
} else { |
4280
|
|
|
$this->message = sprintf( _x( 'You have successfully set %s as Jetpack’s primary user.', '%s is a username', 'jetpack' ), $master_userdata->user_login ); |
4281
|
|
|
} |
4282
|
|
|
break; |
4283
|
|
|
} |
4284
|
|
|
|
4285
|
|
|
$deactivated_plugins = Jetpack::state( 'deactivated_plugins' ); |
4286
|
|
|
|
4287
|
|
|
if ( ! empty( $deactivated_plugins ) ) { |
4288
|
|
|
$deactivated_plugins = explode( ',', $deactivated_plugins ); |
4289
|
|
|
$deactivated_titles = array(); |
4290
|
|
|
foreach ( $deactivated_plugins as $deactivated_plugin ) { |
4291
|
|
|
if ( ! isset( $this->plugins_to_deactivate[$deactivated_plugin] ) ) { |
4292
|
|
|
continue; |
4293
|
|
|
} |
4294
|
|
|
|
4295
|
|
|
$deactivated_titles[] = '<strong>' . str_replace( ' ', ' ', $this->plugins_to_deactivate[$deactivated_plugin][1] ) . '</strong>'; |
4296
|
|
|
} |
4297
|
|
|
|
4298
|
|
|
if ( $deactivated_titles ) { |
|
|
|
|
4299
|
|
|
if ( $this->message ) { |
4300
|
|
|
$this->message .= "<br /><br />\n"; |
4301
|
|
|
} |
4302
|
|
|
|
4303
|
|
|
$this->message .= wp_sprintf( |
4304
|
|
|
_n( |
4305
|
|
|
'Jetpack contains the most recent version of the old %l plugin.', |
4306
|
|
|
'Jetpack contains the most recent versions of the old %l plugins.', |
4307
|
|
|
count( $deactivated_titles ), |
4308
|
|
|
'jetpack' |
4309
|
|
|
), |
4310
|
|
|
$deactivated_titles |
4311
|
|
|
); |
4312
|
|
|
|
4313
|
|
|
$this->message .= "<br />\n"; |
4314
|
|
|
|
4315
|
|
|
$this->message .= _n( |
4316
|
|
|
'The old version has been deactivated and can be removed from your site.', |
4317
|
|
|
'The old versions have been deactivated and can be removed from your site.', |
4318
|
|
|
count( $deactivated_titles ), |
4319
|
|
|
'jetpack' |
4320
|
|
|
); |
4321
|
|
|
} |
4322
|
|
|
} |
4323
|
|
|
|
4324
|
|
|
$this->privacy_checks = Jetpack::state( 'privacy_checks' ); |
4325
|
|
|
|
4326
|
|
|
if ( $this->message || $this->error || $this->privacy_checks || $this->can_display_jetpack_manage_notice() ) { |
4327
|
|
|
add_action( 'jetpack_notices', array( $this, 'admin_notices' ) ); |
4328
|
|
|
} |
4329
|
|
|
|
4330
|
|
View Code Duplication |
if ( isset( $_GET['configure'] ) && Jetpack::is_module( $_GET['configure'] ) && current_user_can( 'manage_options' ) ) { |
4331
|
|
|
/** |
4332
|
|
|
* Fires when a module configuration page is loaded. |
4333
|
|
|
* The dynamic part of the hook is the configure parameter from the URL. |
4334
|
|
|
* |
4335
|
|
|
* @since 1.1.0 |
4336
|
|
|
*/ |
4337
|
|
|
do_action( 'jetpack_module_configuration_load_' . $_GET['configure'] ); |
4338
|
|
|
} |
4339
|
|
|
|
4340
|
|
|
add_filter( 'jetpack_short_module_description', 'wptexturize' ); |
4341
|
|
|
} |
4342
|
|
|
|
4343
|
|
|
function admin_notices() { |
4344
|
|
|
|
4345
|
|
|
if ( $this->error ) { |
4346
|
|
|
?> |
4347
|
|
|
<div id="message" class="jetpack-message jetpack-err"> |
4348
|
|
|
<div class="squeezer"> |
4349
|
|
|
<h2><?php echo wp_kses( $this->error, array( 'code' => true, 'strong' => true, 'br' => true, 'b' => true ) ); ?></h2> |
4350
|
|
|
<?php if ( $desc = Jetpack::state( 'error_description' ) ) : ?> |
4351
|
|
|
<p><?php echo esc_html( stripslashes( $desc ) ); ?></p> |
4352
|
|
|
<?php endif; ?> |
4353
|
|
|
</div> |
4354
|
|
|
</div> |
4355
|
|
|
<?php |
4356
|
|
|
} |
4357
|
|
|
|
4358
|
|
|
if ( $this->message ) { |
4359
|
|
|
?> |
4360
|
|
|
<div id="message" class="jetpack-message"> |
4361
|
|
|
<div class="squeezer"> |
4362
|
|
|
<h2><?php echo wp_kses( $this->message, array( 'strong' => array(), 'a' => array( 'href' => true ), 'br' => true ) ); ?></h2> |
4363
|
|
|
</div> |
4364
|
|
|
</div> |
4365
|
|
|
<?php |
4366
|
|
|
} |
4367
|
|
|
|
4368
|
|
|
if ( $this->privacy_checks ) : |
4369
|
|
|
$module_names = $module_slugs = array(); |
4370
|
|
|
|
4371
|
|
|
$privacy_checks = explode( ',', $this->privacy_checks ); |
4372
|
|
|
$privacy_checks = array_filter( $privacy_checks, array( 'Jetpack', 'is_module' ) ); |
4373
|
|
|
foreach ( $privacy_checks as $module_slug ) { |
4374
|
|
|
$module = Jetpack::get_module( $module_slug ); |
4375
|
|
|
if ( ! $module ) { |
4376
|
|
|
continue; |
4377
|
|
|
} |
4378
|
|
|
|
4379
|
|
|
$module_slugs[] = $module_slug; |
4380
|
|
|
$module_names[] = "<strong>{$module['name']}</strong>"; |
4381
|
|
|
} |
4382
|
|
|
|
4383
|
|
|
$module_slugs = join( ',', $module_slugs ); |
4384
|
|
|
?> |
4385
|
|
|
<div id="message" class="jetpack-message jetpack-err"> |
4386
|
|
|
<div class="squeezer"> |
4387
|
|
|
<h2><strong><?php esc_html_e( 'Is this site private?', 'jetpack' ); ?></strong></h2><br /> |
4388
|
|
|
<p><?php |
4389
|
|
|
echo wp_kses( |
4390
|
|
|
wptexturize( |
4391
|
|
|
wp_sprintf( |
4392
|
|
|
_nx( |
4393
|
|
|
"Like your site's RSS feeds, %l allows access to your posts and other content to third parties.", |
4394
|
|
|
"Like your site's RSS feeds, %l allow access to your posts and other content to third parties.", |
4395
|
|
|
count( $privacy_checks ), |
4396
|
|
|
'%l = list of Jetpack module/feature names', |
4397
|
|
|
'jetpack' |
4398
|
|
|
), |
4399
|
|
|
$module_names |
4400
|
|
|
) |
4401
|
|
|
), |
4402
|
|
|
array( 'strong' => true ) |
4403
|
|
|
); |
4404
|
|
|
|
4405
|
|
|
echo "\n<br />\n"; |
4406
|
|
|
|
4407
|
|
|
echo wp_kses( |
4408
|
|
|
sprintf( |
4409
|
|
|
_nx( |
4410
|
|
|
'If your site is not publicly accessible, consider <a href="%1$s" title="%2$s">deactivating this feature</a>.', |
4411
|
|
|
'If your site is not publicly accessible, consider <a href="%1$s" title="%2$s">deactivating these features</a>.', |
4412
|
|
|
count( $privacy_checks ), |
4413
|
|
|
'%1$s = deactivation URL, %2$s = "Deactivate {list of Jetpack module/feature names}', |
4414
|
|
|
'jetpack' |
4415
|
|
|
), |
4416
|
|
|
wp_nonce_url( |
4417
|
|
|
Jetpack::admin_url( |
4418
|
|
|
array( |
4419
|
|
|
'page' => 'jetpack', |
4420
|
|
|
'action' => 'deactivate', |
4421
|
|
|
'module' => urlencode( $module_slugs ), |
4422
|
|
|
) |
4423
|
|
|
), |
4424
|
|
|
"jetpack_deactivate-$module_slugs" |
4425
|
|
|
), |
4426
|
|
|
esc_attr( wp_kses( wp_sprintf( _x( 'Deactivate %l', '%l = list of Jetpack module/feature names', 'jetpack' ), $module_names ), array() ) ) |
4427
|
|
|
), |
4428
|
|
|
array( 'a' => array( 'href' => true, 'title' => true ) ) |
4429
|
|
|
); |
4430
|
|
|
?></p> |
4431
|
|
|
</div> |
4432
|
|
|
</div> |
4433
|
|
|
<?php endif; |
4434
|
|
|
// only display the notice if the other stuff is not there |
4435
|
|
|
if( $this->can_display_jetpack_manage_notice() && ! $this->error && ! $this->message && ! $this->privacy_checks ) { |
4436
|
|
|
if( isset( $_GET['page'] ) && 'jetpack' != $_GET['page'] ) |
4437
|
|
|
$this->opt_in_jetpack_manage_notice(); |
4438
|
|
|
} |
4439
|
|
|
} |
4440
|
|
|
|
4441
|
|
|
/** |
4442
|
|
|
* Record a stat for later output. This will only currently output in the admin_footer. |
4443
|
|
|
*/ |
4444
|
|
|
function stat( $group, $detail ) { |
4445
|
|
|
if ( ! isset( $this->stats[ $group ] ) ) |
4446
|
|
|
$this->stats[ $group ] = array(); |
4447
|
|
|
$this->stats[ $group ][] = $detail; |
4448
|
|
|
} |
4449
|
|
|
|
4450
|
|
|
/** |
4451
|
|
|
* Load stats pixels. $group is auto-prefixed with "x_jetpack-" |
4452
|
|
|
*/ |
4453
|
|
|
function do_stats( $method = '' ) { |
4454
|
|
|
if ( is_array( $this->stats ) && count( $this->stats ) ) { |
4455
|
|
|
foreach ( $this->stats as $group => $stats ) { |
4456
|
|
|
if ( is_array( $stats ) && count( $stats ) ) { |
4457
|
|
|
$args = array( "x_jetpack-{$group}" => implode( ',', $stats ) ); |
4458
|
|
|
if ( 'server_side' === $method ) { |
4459
|
|
|
self::do_server_side_stat( $args ); |
4460
|
|
|
} else { |
4461
|
|
|
echo '<img src="' . esc_url( self::build_stats_url( $args ) ) . '" width="1" height="1" style="display:none;" />'; |
4462
|
|
|
} |
4463
|
|
|
} |
4464
|
|
|
unset( $this->stats[ $group ] ); |
4465
|
|
|
} |
4466
|
|
|
} |
4467
|
|
|
} |
4468
|
|
|
|
4469
|
|
|
/** |
4470
|
|
|
* Runs stats code for a one-off, server-side. |
4471
|
|
|
* |
4472
|
|
|
* @param $args array|string The arguments to append to the URL. Should include `x_jetpack-{$group}={$stats}` or whatever we want to store. |
4473
|
|
|
* |
4474
|
|
|
* @return bool If it worked. |
4475
|
|
|
*/ |
4476
|
|
|
static function do_server_side_stat( $args ) { |
4477
|
|
|
$response = wp_remote_get( esc_url_raw( self::build_stats_url( $args ) ) ); |
4478
|
|
|
if ( is_wp_error( $response ) ) |
4479
|
|
|
return false; |
4480
|
|
|
|
4481
|
|
|
if ( 200 !== wp_remote_retrieve_response_code( $response ) ) |
4482
|
|
|
return false; |
4483
|
|
|
|
4484
|
|
|
return true; |
4485
|
|
|
} |
4486
|
|
|
|
4487
|
|
|
/** |
4488
|
|
|
* Builds the stats url. |
4489
|
|
|
* |
4490
|
|
|
* @param $args array|string The arguments to append to the URL. |
4491
|
|
|
* |
4492
|
|
|
* @return string The URL to be pinged. |
4493
|
|
|
*/ |
4494
|
|
|
static function build_stats_url( $args ) { |
4495
|
|
|
$defaults = array( |
4496
|
|
|
'v' => 'wpcom2', |
4497
|
|
|
'rand' => md5( mt_rand( 0, 999 ) . time() ), |
4498
|
|
|
); |
4499
|
|
|
$args = wp_parse_args( $args, $defaults ); |
4500
|
|
|
/** |
4501
|
|
|
* Filter the URL used as the Stats tracking pixel. |
4502
|
|
|
* |
4503
|
|
|
* @since 2.3.2 |
4504
|
|
|
* |
4505
|
|
|
* @param string $url Base URL used as the Stats tracking pixel. |
4506
|
|
|
*/ |
4507
|
|
|
$base_url = apply_filters( |
4508
|
|
|
'jetpack_stats_base_url', |
4509
|
|
|
set_url_scheme( 'http://pixel.wp.com/g.gif' ) |
4510
|
|
|
); |
4511
|
|
|
$url = add_query_arg( $args, $base_url ); |
4512
|
|
|
return $url; |
4513
|
|
|
} |
4514
|
|
|
|
4515
|
|
|
function translate_current_user_to_role() { |
4516
|
|
|
foreach ( $this->capability_translations as $role => $cap ) { |
4517
|
|
|
if ( current_user_can( $role ) || current_user_can( $cap ) ) { |
4518
|
|
|
return $role; |
4519
|
|
|
} |
4520
|
|
|
} |
4521
|
|
|
|
4522
|
|
|
return false; |
4523
|
|
|
} |
4524
|
|
|
|
4525
|
|
|
function translate_role_to_cap( $role ) { |
4526
|
|
|
if ( ! isset( $this->capability_translations[$role] ) ) { |
4527
|
|
|
return false; |
4528
|
|
|
} |
4529
|
|
|
|
4530
|
|
|
return $this->capability_translations[$role]; |
4531
|
|
|
} |
4532
|
|
|
|
4533
|
|
|
function sign_role( $role ) { |
4534
|
|
|
if ( ! $user_id = (int) get_current_user_id() ) { |
4535
|
|
|
return false; |
4536
|
|
|
} |
4537
|
|
|
|
4538
|
|
|
$token = Jetpack_Data::get_access_token(); |
4539
|
|
|
if ( ! $token || is_wp_error( $token ) ) { |
4540
|
|
|
return false; |
4541
|
|
|
} |
4542
|
|
|
|
4543
|
|
|
return $role . ':' . hash_hmac( 'md5', "{$role}|{$user_id}", $token->secret ); |
4544
|
|
|
} |
4545
|
|
|
|
4546
|
|
|
function build_connect_url( $raw = false, $redirect = false ) { |
4547
|
|
|
if ( ! Jetpack_Options::get_option( 'blog_token' ) || ! Jetpack_Options::get_option( 'id' ) ) { |
4548
|
|
|
$url = Jetpack::nonce_url_no_esc( Jetpack::admin_url( 'action=register' ), 'jetpack-register' ); |
4549
|
|
|
if( is_network_admin() ) { |
4550
|
|
|
$url = add_query_arg( 'is_multisite', network_admin_url( |
4551
|
|
|
'admin.php?page=jetpack-settings' ), $url ); |
4552
|
|
|
} |
4553
|
|
|
} else { |
4554
|
|
|
$role = $this->translate_current_user_to_role(); |
4555
|
|
|
$signed_role = $this->sign_role( $role ); |
4556
|
|
|
|
4557
|
|
|
$user = wp_get_current_user(); |
4558
|
|
|
|
4559
|
|
|
$redirect = $redirect ? esc_url_raw( $redirect ) : ''; |
4560
|
|
|
|
4561
|
|
|
if( isset( $_REQUEST['is_multisite'] ) ) { |
4562
|
|
|
$redirect = Jetpack_Network::init()->get_url( 'network_admin_page' ); |
4563
|
|
|
} |
4564
|
|
|
|
4565
|
|
|
$args = urlencode_deep( |
4566
|
|
|
array( |
4567
|
|
|
'response_type' => 'code', |
4568
|
|
|
'client_id' => Jetpack_Options::get_option( 'id' ), |
4569
|
|
|
'redirect_uri' => add_query_arg( |
4570
|
|
|
array( |
4571
|
|
|
'action' => 'authorize', |
4572
|
|
|
'_wpnonce' => wp_create_nonce( "jetpack-authorize_{$role}_{$redirect}" ), |
4573
|
|
|
'redirect' => $redirect ? urlencode( $redirect ) : false, |
4574
|
|
|
), |
4575
|
|
|
menu_page_url( 'jetpack', false ) |
4576
|
|
|
), |
4577
|
|
|
'state' => $user->ID, |
4578
|
|
|
'scope' => $signed_role, |
4579
|
|
|
'user_email' => $user->user_email, |
4580
|
|
|
'user_login' => $user->user_login, |
4581
|
|
|
'is_active' => Jetpack::is_active(), |
4582
|
|
|
'jp_version' => JETPACK__VERSION, |
4583
|
|
|
) |
4584
|
|
|
); |
4585
|
|
|
|
4586
|
|
|
$url = add_query_arg( $args, Jetpack::api_url( 'authorize' ) ); |
4587
|
|
|
} |
4588
|
|
|
|
4589
|
|
|
return $raw ? $url : esc_url( $url ); |
4590
|
|
|
} |
4591
|
|
|
|
4592
|
|
|
function build_reconnect_url( $raw = false ) { |
4593
|
|
|
$url = wp_nonce_url( Jetpack::admin_url( 'action=reconnect' ), 'jetpack-reconnect' ); |
4594
|
|
|
return $raw ? $url : esc_url( $url ); |
4595
|
|
|
} |
4596
|
|
|
|
4597
|
|
|
public static function admin_url( $args = null ) { |
4598
|
|
|
$args = wp_parse_args( $args, array( 'page' => 'jetpack' ) ); |
4599
|
|
|
$url = add_query_arg( $args, admin_url( 'admin.php' ) ); |
4600
|
|
|
return $url; |
4601
|
|
|
} |
4602
|
|
|
|
4603
|
|
|
public static function nonce_url_no_esc( $actionurl, $action = -1, $name = '_wpnonce' ) { |
4604
|
|
|
$actionurl = str_replace( '&', '&', $actionurl ); |
4605
|
|
|
return add_query_arg( $name, wp_create_nonce( $action ), $actionurl ); |
4606
|
|
|
} |
4607
|
|
|
|
4608
|
|
|
function dismiss_jetpack_notice() { |
4609
|
|
|
|
4610
|
|
|
if ( ! isset( $_GET['jetpack-notice'] ) ) { |
4611
|
|
|
return; |
4612
|
|
|
} |
4613
|
|
|
|
4614
|
|
|
switch( $_GET['jetpack-notice'] ) { |
4615
|
|
|
case 'dismiss': |
4616
|
|
|
if ( check_admin_referer( 'jetpack-deactivate' ) && ! is_plugin_active_for_network( plugin_basename( JETPACK__PLUGIN_DIR . 'jetpack.php' ) ) ) { |
4617
|
|
|
|
4618
|
|
|
require_once ABSPATH . 'wp-admin/includes/plugin.php'; |
4619
|
|
|
deactivate_plugins( JETPACK__PLUGIN_DIR . 'jetpack.php', false, false ); |
4620
|
|
|
wp_safe_redirect( admin_url() . 'plugins.php?deactivate=true&plugin_status=all&paged=1&s=' ); |
4621
|
|
|
} |
4622
|
|
|
break; |
4623
|
|
View Code Duplication |
case 'jetpack-manage-opt-out': |
4624
|
|
|
|
4625
|
|
|
if ( check_admin_referer( 'jetpack_manage_banner_opt_out' ) ) { |
4626
|
|
|
// Don't show the banner again |
4627
|
|
|
|
4628
|
|
|
Jetpack_Options::update_option( 'dismissed_manage_banner', true ); |
4629
|
|
|
// redirect back to the page that had the notice |
4630
|
|
|
if ( wp_get_referer() ) { |
4631
|
|
|
wp_safe_redirect( wp_get_referer() ); |
4632
|
|
|
} else { |
4633
|
|
|
// Take me to Jetpack |
4634
|
|
|
wp_safe_redirect( admin_url( 'admin.php?page=jetpack' ) ); |
4635
|
|
|
} |
4636
|
|
|
} |
4637
|
|
|
break; |
4638
|
|
View Code Duplication |
case 'jetpack-protect-multisite-opt-out': |
4639
|
|
|
|
4640
|
|
|
if ( check_admin_referer( 'jetpack_protect_multisite_banner_opt_out' ) ) { |
4641
|
|
|
// Don't show the banner again |
4642
|
|
|
|
4643
|
|
|
update_site_option( 'jetpack_dismissed_protect_multisite_banner', true ); |
4644
|
|
|
// redirect back to the page that had the notice |
4645
|
|
|
if ( wp_get_referer() ) { |
4646
|
|
|
wp_safe_redirect( wp_get_referer() ); |
4647
|
|
|
} else { |
4648
|
|
|
// Take me to Jetpack |
4649
|
|
|
wp_safe_redirect( admin_url( 'admin.php?page=jetpack' ) ); |
4650
|
|
|
} |
4651
|
|
|
} |
4652
|
|
|
break; |
4653
|
|
|
case 'jetpack-manage-opt-in': |
4654
|
|
|
if ( check_admin_referer( 'jetpack_manage_banner_opt_in' ) ) { |
4655
|
|
|
// This makes sure that we are redirect to jetpack home so that we can see the Success Message. |
4656
|
|
|
|
4657
|
|
|
$redirection_url = Jetpack::admin_url(); |
4658
|
|
|
remove_action( 'jetpack_pre_activate_module', array( Jetpack_Admin::init(), 'fix_redirect' ) ); |
4659
|
|
|
|
4660
|
|
|
// Don't redirect form the Jetpack Setting Page |
4661
|
|
|
$referer_parsed = parse_url ( wp_get_referer() ); |
4662
|
|
|
// check that we do have a wp_get_referer and the query paramater is set orderwise go to the Jetpack Home |
4663
|
|
|
if ( isset( $referer_parsed['query'] ) && false !== strpos( $referer_parsed['query'], 'page=jetpack_modules' ) ) { |
4664
|
|
|
// Take the user to Jetpack home except when on the setting page |
4665
|
|
|
$redirection_url = wp_get_referer(); |
4666
|
|
|
add_action( 'jetpack_pre_activate_module', array( Jetpack_Admin::init(), 'fix_redirect' ) ); |
4667
|
|
|
} |
4668
|
|
|
// Also update the JSON API FULL MANAGEMENT Option |
4669
|
|
|
Jetpack::activate_module( 'manage', false, false ); |
4670
|
|
|
|
4671
|
|
|
// Special Message when option in. |
4672
|
|
|
Jetpack::state( 'optin-manage', 'true' ); |
4673
|
|
|
// Activate the Module if not activated already |
4674
|
|
|
|
4675
|
|
|
// Redirect properly |
4676
|
|
|
wp_safe_redirect( $redirection_url ); |
4677
|
|
|
|
4678
|
|
|
} |
4679
|
|
|
break; |
4680
|
|
|
} |
4681
|
|
|
} |
4682
|
|
|
|
4683
|
|
|
function debugger_page() { |
4684
|
|
|
nocache_headers(); |
4685
|
|
|
if ( ! current_user_can( 'manage_options' ) ) { |
4686
|
|
|
die( '-1' ); |
|
|
|
|
4687
|
|
|
} |
4688
|
|
|
Jetpack_Debugger::jetpack_debug_display_handler(); |
4689
|
|
|
exit; |
|
|
|
|
4690
|
|
|
} |
4691
|
|
|
|
4692
|
|
|
public static function admin_screen_configure_module( $module_id ) { |
4693
|
|
|
|
4694
|
|
|
// User that doesn't have 'jetpack_configure_modules' will never end up here since Jetpack Landing Page woun't let them. |
4695
|
|
|
if ( ! in_array( $module_id, Jetpack::get_active_modules() ) && current_user_can( 'manage_options' ) ) { |
4696
|
|
|
if ( has_action( 'display_activate_module_setting_' . $module_id ) ) { |
4697
|
|
|
/** |
4698
|
|
|
* Fires to diplay a custom module activation screen. |
4699
|
|
|
* |
4700
|
|
|
* To add a module actionation screen use Jetpack::module_configuration_activation_screen method. |
4701
|
|
|
* Example: Jetpack::module_configuration_activation_screen( 'manage', array( $this, 'manage_activate_screen' ) ); |
4702
|
|
|
* |
4703
|
|
|
* @module manage |
4704
|
|
|
* |
4705
|
|
|
* @since 3.8.0 |
4706
|
|
|
* |
4707
|
|
|
* @param int $module_id Module ID. |
4708
|
|
|
*/ |
4709
|
|
|
do_action( 'display_activate_module_setting_' . $module_id ); |
4710
|
|
|
} else { |
4711
|
|
|
self::display_activate_module_link( $module_id ); |
4712
|
|
|
} |
4713
|
|
|
|
4714
|
|
|
return false; |
4715
|
|
|
} ?> |
4716
|
|
|
|
4717
|
|
|
<div id="jp-settings-screen" style="position: relative"> |
4718
|
|
|
<h3> |
4719
|
|
|
<?php |
4720
|
|
|
$module = Jetpack::get_module( $module_id ); |
4721
|
|
|
echo '<a href="' . Jetpack::admin_url( 'page=jetpack_modules' ) . '">' . __( 'Jetpack by WordPress.com', 'jetpack' ) . '</a> → '; |
4722
|
|
|
printf( __( 'Configure %s', 'jetpack' ), $module['name'] ); |
4723
|
|
|
?> |
4724
|
|
|
</h3> |
4725
|
|
|
<?php |
4726
|
|
|
/** |
4727
|
|
|
* Fires within the displayed message when a feature configuation is updated. |
4728
|
|
|
* |
4729
|
|
|
* @since 3.4.0 |
4730
|
|
|
* |
4731
|
|
|
* @param int $module_id Module ID. |
4732
|
|
|
*/ |
4733
|
|
|
do_action( 'jetpack_notices_update_settings', $module_id ); |
4734
|
|
|
/** |
4735
|
|
|
* Fires when a feature configuation screen is loaded. |
4736
|
|
|
* The dynamic part of the hook, $module_id, is the module ID. |
4737
|
|
|
* |
4738
|
|
|
* @since 1.1.0 |
4739
|
|
|
*/ |
4740
|
|
|
do_action( 'jetpack_module_configuration_screen_' . $module_id ); |
4741
|
|
|
?> |
4742
|
|
|
</div><?php |
4743
|
|
|
} |
4744
|
|
|
|
4745
|
|
|
/** |
4746
|
|
|
* Display link to activate the module to see the settings screen. |
4747
|
|
|
* @param string $module_id |
4748
|
|
|
* @return null |
4749
|
|
|
*/ |
4750
|
|
|
public static function display_activate_module_link( $module_id ) { |
4751
|
|
|
|
4752
|
|
|
$info = Jetpack::get_module( $module_id ); |
4753
|
|
|
$extra = ''; |
4754
|
|
|
$activate_url = wp_nonce_url( |
4755
|
|
|
Jetpack::admin_url( |
4756
|
|
|
array( |
4757
|
|
|
'page' => 'jetpack', |
4758
|
|
|
'action' => 'activate', |
4759
|
|
|
'module' => $module_id, |
4760
|
|
|
) |
4761
|
|
|
), |
4762
|
|
|
"jetpack_activate-$module_id" |
4763
|
|
|
); |
4764
|
|
|
|
4765
|
|
|
?> |
4766
|
|
|
|
4767
|
|
|
<div class="wrap configure-module"> |
4768
|
|
|
<div id="jp-settings-screen"> |
4769
|
|
|
<?php |
4770
|
|
|
if ( $module_id == 'json-api' ) { |
4771
|
|
|
|
4772
|
|
|
$info['name'] = esc_html__( 'Activate Site Management and JSON API', 'jetpack' ); |
4773
|
|
|
|
4774
|
|
|
$activate_url = Jetpack::init()->opt_in_jetpack_manage_url(); |
4775
|
|
|
|
4776
|
|
|
$info['description'] = sprintf( __( 'Manage your multiple Jetpack sites from our centralized dashboard at wordpress.com/sites. <a href="%s" target="_blank">Learn more</a>.', 'jetpack' ), 'http://jetpack.me/support/site-management' ); |
4777
|
|
|
|
4778
|
|
|
// $extra = __( 'To use Site Management, you need to first activate JSON API to allow remote management of your site. ', 'jetpack' ); |
4779
|
|
|
} ?> |
4780
|
|
|
|
4781
|
|
|
<h3><?php echo esc_html( $info['name'] ); ?></h3> |
4782
|
|
|
<div class="narrow"> |
4783
|
|
|
<p><?php echo $info['description']; ?></p> |
4784
|
|
|
<?php if( $extra ) { ?> |
4785
|
|
|
<p><?php echo esc_html( $extra ); ?></p> |
4786
|
|
|
<?php } ?> |
4787
|
|
|
<p> |
4788
|
|
|
<?php |
4789
|
|
|
if( wp_get_referer() ) { |
4790
|
|
|
printf( __( '<a class="button-primary" href="%s">Activate Now</a> or <a href="%s" >return to previous page</a>.', 'jetpack' ) , $activate_url, wp_get_referer() ); |
4791
|
|
|
} else { |
4792
|
|
|
printf( __( '<a class="button-primary" href="%s">Activate Now</a>', 'jetpack' ) , $activate_url ); |
4793
|
|
|
} ?> |
4794
|
|
|
</p> |
4795
|
|
|
</div> |
4796
|
|
|
|
4797
|
|
|
</div> |
4798
|
|
|
</div> |
4799
|
|
|
|
4800
|
|
|
<?php |
4801
|
|
|
} |
4802
|
|
|
|
4803
|
|
|
public static function sort_modules( $a, $b ) { |
4804
|
|
|
if ( $a['sort'] == $b['sort'] ) |
4805
|
|
|
return 0; |
4806
|
|
|
|
4807
|
|
|
return ( $a['sort'] < $b['sort'] ) ? -1 : 1; |
4808
|
|
|
} |
4809
|
|
|
|
4810
|
|
View Code Duplication |
function sync_reindex_trigger() { |
4811
|
|
|
if ( $this->current_user_is_connection_owner() && current_user_can( 'manage_options' ) ) { |
4812
|
|
|
echo json_encode( $this->sync->reindex_trigger() ); |
4813
|
|
|
} else { |
4814
|
|
|
echo '{"status":"ERROR"}'; |
4815
|
|
|
} |
4816
|
|
|
exit; |
|
|
|
|
4817
|
|
|
} |
4818
|
|
|
|
4819
|
|
View Code Duplication |
function sync_reindex_status(){ |
4820
|
|
|
if ( $this->current_user_is_connection_owner() && current_user_can( 'manage_options' ) ) { |
4821
|
|
|
echo json_encode( $this->sync->reindex_status() ); |
4822
|
|
|
} else { |
4823
|
|
|
echo '{"status":"ERROR"}'; |
4824
|
|
|
} |
4825
|
|
|
exit; |
|
|
|
|
4826
|
|
|
} |
4827
|
|
|
|
4828
|
|
|
/* Client API */ |
4829
|
|
|
|
4830
|
|
|
/** |
4831
|
|
|
* Returns the requested Jetpack API URL |
4832
|
|
|
* |
4833
|
|
|
* @return string |
4834
|
|
|
*/ |
4835
|
|
|
public static function api_url( $relative_url ) { |
4836
|
|
|
return trailingslashit( JETPACK__API_BASE . $relative_url ) . JETPACK__API_VERSION . '/'; |
4837
|
|
|
} |
4838
|
|
|
|
4839
|
|
|
/** |
4840
|
|
|
* Some hosts disable the OpenSSL extension and so cannot make outgoing HTTPS requsets |
4841
|
|
|
*/ |
4842
|
|
|
public static function fix_url_for_bad_hosts( $url ) { |
4843
|
|
|
if ( 0 !== strpos( $url, 'https://' ) ) { |
4844
|
|
|
return $url; |
4845
|
|
|
} |
4846
|
|
|
|
4847
|
|
|
switch ( JETPACK_CLIENT__HTTPS ) { |
4848
|
|
|
case 'ALWAYS' : |
4849
|
|
|
return $url; |
4850
|
|
|
case 'NEVER' : |
4851
|
|
|
return set_url_scheme( $url, 'http' ); |
4852
|
|
|
// default : case 'AUTO' : |
4853
|
|
|
} |
4854
|
|
|
|
4855
|
|
|
// Yay! Your host is good! |
4856
|
|
|
if ( self::permit_ssl() && wp_http_supports( array( 'ssl' => true ) ) ) { |
4857
|
|
|
return $url; |
4858
|
|
|
} |
4859
|
|
|
|
4860
|
|
|
// Boo! Your host is bad and makes Jetpack cry! |
4861
|
|
|
return set_url_scheme( $url, 'http' ); |
4862
|
|
|
} |
4863
|
|
|
|
4864
|
|
|
/** |
4865
|
|
|
* Checks to see if the URL is using SSL to connect with Jetpack |
4866
|
|
|
* |
4867
|
|
|
* @since 2.3.3 |
4868
|
|
|
* @return boolean |
4869
|
|
|
*/ |
4870
|
|
|
public static function permit_ssl( $force_recheck = false ) { |
4871
|
|
|
// Do some fancy tests to see if ssl is being supported |
4872
|
|
|
if ( $force_recheck || false === ( $ssl = get_transient( 'jetpack_https_test' ) ) ) { |
4873
|
|
|
if ( 'https' !== substr( JETPACK__API_BASE, 0, 5 ) ) { |
4874
|
|
|
$ssl = 0; |
4875
|
|
|
} else { |
4876
|
|
|
switch ( JETPACK_CLIENT__HTTPS ) { |
4877
|
|
|
case 'NEVER': |
4878
|
|
|
$ssl = 0; |
4879
|
|
|
break; |
4880
|
|
|
case 'ALWAYS': |
4881
|
|
|
case 'AUTO': |
4882
|
|
|
default: |
4883
|
|
|
$ssl = 1; |
4884
|
|
|
break; |
4885
|
|
|
} |
4886
|
|
|
|
4887
|
|
|
// If it's not 'NEVER', test to see |
4888
|
|
|
if ( $ssl ) { |
4889
|
|
|
$response = wp_remote_get( JETPACK__API_BASE . 'test/1/' ); |
4890
|
|
|
if ( is_wp_error( $response ) || ( 'OK' !== wp_remote_retrieve_body( $response ) ) ) { |
4891
|
|
|
$ssl = 0; |
4892
|
|
|
} |
4893
|
|
|
} |
4894
|
|
|
} |
4895
|
|
|
set_transient( 'jetpack_https_test', $ssl, DAY_IN_SECONDS ); |
4896
|
|
|
} |
4897
|
|
|
|
4898
|
|
|
return (bool) $ssl; |
4899
|
|
|
} |
4900
|
|
|
|
4901
|
|
|
/* |
4902
|
|
|
* Displays an admin_notice, alerting the user to their JETPACK_CLIENT__HTTPS constant being 'ALWAYS' but SSL isn't working. |
4903
|
|
|
*/ |
4904
|
|
|
public function alert_required_ssl_fail() { |
4905
|
|
|
if ( ! current_user_can( 'manage_options' ) ) |
4906
|
|
|
return; |
4907
|
|
|
?> |
4908
|
|
|
|
4909
|
|
|
<div id="message" class="error jetpack-message jp-identity-crisis"> |
4910
|
|
|
<div class="jp-banner__content"> |
4911
|
|
|
<h2><?php _e( 'Something is being cranky!', 'jetpack' ); ?></h2> |
4912
|
|
|
<p><?php _e( 'Your site is configured to only permit SSL connections to Jetpack, but SSL connections don\'t seem to be functional!', 'jetpack' ); ?></p> |
4913
|
|
|
</div> |
4914
|
|
|
</div> |
4915
|
|
|
|
4916
|
|
|
<?php |
4917
|
|
|
} |
4918
|
|
|
|
4919
|
|
|
/** |
4920
|
|
|
* Returns the Jetpack XML-RPC API |
4921
|
|
|
* |
4922
|
|
|
* @return string |
4923
|
|
|
*/ |
4924
|
|
|
public static function xmlrpc_api_url() { |
4925
|
|
|
$base = preg_replace( '#(https?://[^?/]+)(/?.*)?$#', '\\1', JETPACK__API_BASE ); |
4926
|
|
|
return untrailingslashit( $base ) . '/xmlrpc.php'; |
4927
|
|
|
} |
4928
|
|
|
|
4929
|
|
|
/** |
4930
|
|
|
* Creates two secret tokens and the end of life timestamp for them. |
4931
|
|
|
* |
4932
|
|
|
* Note these tokens are unique per call, NOT static per site for connecting. |
4933
|
|
|
* |
4934
|
|
|
* @since 2.6 |
4935
|
|
|
* @return array |
4936
|
|
|
*/ |
4937
|
|
|
public function generate_secrets() { |
4938
|
|
|
$secrets = array( |
4939
|
|
|
wp_generate_password( 32, false ), // secret_1 |
4940
|
|
|
wp_generate_password( 32, false ), // secret_2 |
4941
|
|
|
( time() + 600 ), // eol ( End of Life ) |
4942
|
|
|
); |
4943
|
|
|
|
4944
|
|
|
return $secrets; |
4945
|
|
|
} |
4946
|
|
|
|
4947
|
|
|
/** |
4948
|
|
|
* Builds the timeout limit for queries talking with the wpcom servers. |
4949
|
|
|
* |
4950
|
|
|
* Based on local php max_execution_time in php.ini |
4951
|
|
|
* |
4952
|
|
|
* @since 2.6 |
4953
|
|
|
* @return int |
4954
|
|
|
**/ |
4955
|
|
|
public function get_remote_query_timeout_limit() { |
4956
|
|
|
$timeout = (int) ini_get( 'max_execution_time' ); |
4957
|
|
|
if ( ! $timeout ) // Ensure exec time set in php.ini |
4958
|
|
|
$timeout = 30; |
4959
|
|
|
return intval( $timeout / 2 ); |
4960
|
|
|
} |
4961
|
|
|
|
4962
|
|
|
|
4963
|
|
|
/** |
4964
|
|
|
* Takes the response from the Jetpack register new site endpoint and |
4965
|
|
|
* verifies it worked properly. |
4966
|
|
|
* |
4967
|
|
|
* @since 2.6 |
4968
|
|
|
* @return true or Jetpack_Error |
4969
|
|
|
**/ |
4970
|
|
|
public function validate_remote_register_response( $response ) { |
4971
|
|
|
if ( is_wp_error( $response ) ) { |
4972
|
|
|
return new Jetpack_Error( 'register_http_request_failed', $response->get_error_message() ); |
4973
|
|
|
} |
4974
|
|
|
|
4975
|
|
|
$code = wp_remote_retrieve_response_code( $response ); |
4976
|
|
|
$entity = wp_remote_retrieve_body( $response ); |
4977
|
|
|
if ( $entity ) |
4978
|
|
|
$json = json_decode( $entity ); |
4979
|
|
|
else |
4980
|
|
|
$json = false; |
4981
|
|
|
|
4982
|
|
|
$code_type = intval( $code / 100 ); |
4983
|
|
|
if ( 5 == $code_type ) { |
4984
|
|
|
return new Jetpack_Error( 'wpcom_5??', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code ); |
4985
|
|
|
} elseif ( 408 == $code ) { |
4986
|
|
|
return new Jetpack_Error( 'wpcom_408', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code ); |
4987
|
|
|
} elseif ( ! empty( $json->error ) ) { |
4988
|
|
|
$error_description = isset( $json->error_description ) ? sprintf( __( 'Error Details: %s', 'jetpack' ), (string) $json->error_description ) : ''; |
4989
|
|
|
return new Jetpack_Error( (string) $json->error, $error_description, $code ); |
4990
|
|
|
} elseif ( 200 != $code ) { |
4991
|
|
|
return new Jetpack_Error( 'wpcom_bad_response', sprintf( __( 'Error Details: %s', 'jetpack' ), $code ), $code ); |
4992
|
|
|
} |
4993
|
|
|
|
4994
|
|
|
// Jetpack ID error block |
4995
|
|
|
if ( empty( $json->jetpack_id ) ) { |
4996
|
|
|
return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID is empty. Do not publicly post this error message! %s', 'jetpack' ), $entity ), $entity ); |
4997
|
|
|
} elseif ( ! is_scalar( $json->jetpack_id ) ) { |
4998
|
|
|
return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID is not a scalar. Do not publicly post this error message! %s', 'jetpack' ) , $entity ), $entity ); |
4999
|
|
|
} elseif ( preg_match( '/[^0-9]/', $json->jetpack_id ) ) { |
5000
|
|
|
return new Jetpack_Error( 'jetpack_id', sprintf( __( 'Error Details: Jetpack ID begins with a numeral. Do not publicly post this error message! %s', 'jetpack' ) , $entity ), $entity ); |
5001
|
|
|
} |
5002
|
|
|
|
5003
|
|
|
return true; |
5004
|
|
|
} |
5005
|
|
|
/** |
5006
|
|
|
* @return bool|WP_Error |
5007
|
|
|
*/ |
5008
|
|
|
public static function register() { |
5009
|
|
|
add_action( 'pre_update_jetpack_option_register', array( 'Jetpack_Options', 'delete_option' ) ); |
5010
|
|
|
$secrets = Jetpack::init()->generate_secrets(); |
5011
|
|
|
|
5012
|
|
|
Jetpack_Options::update_option( 'register', $secrets[0] . ':' . $secrets[1] . ':' . $secrets[2] ); |
5013
|
|
|
|
5014
|
|
|
@list( $secret_1, $secret_2, $secret_eol ) = explode( ':', Jetpack_Options::get_option( 'register' ) ); |
|
|
|
|
5015
|
|
|
if ( empty( $secret_1 ) || empty( $secret_2 ) || empty( $secret_eol ) || $secret_eol < time() ) { |
5016
|
|
|
return new Jetpack_Error( 'missing_secrets' ); |
5017
|
|
|
} |
5018
|
|
|
|
5019
|
|
|
$timeout = Jetpack::init()->get_remote_query_timeout_limit(); |
5020
|
|
|
|
5021
|
|
|
$gmt_offset = get_option( 'gmt_offset' ); |
5022
|
|
|
if ( ! $gmt_offset ) { |
5023
|
|
|
$gmt_offset = 0; |
5024
|
|
|
} |
5025
|
|
|
|
5026
|
|
|
$stats_options = get_option( 'stats_options' ); |
5027
|
|
|
$stats_id = isset($stats_options['blog_id']) ? $stats_options['blog_id'] : null; |
5028
|
|
|
|
5029
|
|
|
$args = array( |
5030
|
|
|
'method' => 'POST', |
5031
|
|
|
'body' => array( |
5032
|
|
|
'siteurl' => site_url(), |
5033
|
|
|
'home' => home_url(), |
5034
|
|
|
'gmt_offset' => $gmt_offset, |
5035
|
|
|
'timezone_string' => (string) get_option( 'timezone_string' ), |
5036
|
|
|
'site_name' => (string) get_option( 'blogname' ), |
5037
|
|
|
'secret_1' => $secret_1, |
5038
|
|
|
'secret_2' => $secret_2, |
5039
|
|
|
'site_lang' => get_locale(), |
5040
|
|
|
'timeout' => $timeout, |
5041
|
|
|
'stats_id' => $stats_id, |
5042
|
|
|
), |
5043
|
|
|
'headers' => array( |
5044
|
|
|
'Accept' => 'application/json', |
5045
|
|
|
), |
5046
|
|
|
'timeout' => $timeout, |
5047
|
|
|
); |
5048
|
|
|
$response = Jetpack_Client::_wp_remote_request( Jetpack::fix_url_for_bad_hosts( Jetpack::api_url( 'register' ) ), $args, true ); |
5049
|
|
|
|
5050
|
|
|
|
5051
|
|
|
// Make sure the response is valid and does not contain any Jetpack errors |
5052
|
|
|
$valid_response = Jetpack::init()->validate_remote_register_response( $response ); |
5053
|
|
|
if( is_wp_error( $valid_response ) || !$valid_response ) { |
5054
|
|
|
return $valid_response; |
5055
|
|
|
} |
5056
|
|
|
|
5057
|
|
|
// Grab the response values to work with |
5058
|
|
|
$code = wp_remote_retrieve_response_code( $response ); |
5059
|
|
|
$entity = wp_remote_retrieve_body( $response ); |
5060
|
|
|
|
5061
|
|
|
if ( $entity ) |
5062
|
|
|
$json = json_decode( $entity ); |
5063
|
|
|
else |
5064
|
|
|
$json = false; |
5065
|
|
|
|
5066
|
|
View Code Duplication |
if ( empty( $json->jetpack_secret ) || ! is_string( $json->jetpack_secret ) ) |
5067
|
|
|
return new Jetpack_Error( 'jetpack_secret', '', $code ); |
5068
|
|
|
|
5069
|
|
|
if ( isset( $json->jetpack_public ) ) { |
5070
|
|
|
$jetpack_public = (int) $json->jetpack_public; |
5071
|
|
|
} else { |
5072
|
|
|
$jetpack_public = false; |
5073
|
|
|
} |
5074
|
|
|
|
5075
|
|
|
Jetpack_Options::update_options( |
5076
|
|
|
array( |
5077
|
|
|
'id' => (int) $json->jetpack_id, |
5078
|
|
|
'blog_token' => (string) $json->jetpack_secret, |
5079
|
|
|
'public' => $jetpack_public, |
5080
|
|
|
) |
5081
|
|
|
); |
5082
|
|
|
|
5083
|
|
|
/** |
5084
|
|
|
* Fires when a site is registered on WordPress.com. |
5085
|
|
|
* |
5086
|
|
|
* @since 3.7.0 |
5087
|
|
|
* |
5088
|
|
|
* @param int $json->jetpack_id Jetpack Blog ID. |
5089
|
|
|
* @param string $json->jetpack_secret Jetpack Blog Token. |
5090
|
|
|
* @param int|bool $jetpack_public Is the site public. |
5091
|
|
|
*/ |
5092
|
|
|
do_action( 'jetpack_site_registered', $json->jetpack_id, $json->jetpack_secret, $jetpack_public ); |
5093
|
|
|
|
5094
|
|
|
// Initialize Jump Start for the first and only time. |
5095
|
|
|
if ( ! Jetpack_Options::get_option( 'jumpstart' ) ) { |
5096
|
|
|
Jetpack_Options::update_option( 'jumpstart', 'new_connection' ); |
5097
|
|
|
|
5098
|
|
|
$jetpack = Jetpack::init(); |
5099
|
|
|
|
5100
|
|
|
$jetpack->stat( 'jumpstart', 'unique-views' ); |
5101
|
|
|
$jetpack->do_stats( 'server_side' ); |
5102
|
|
|
}; |
5103
|
|
|
|
5104
|
|
|
return true; |
5105
|
|
|
} |
5106
|
|
|
|
5107
|
|
|
/** |
5108
|
|
|
* If the db version is showing something other that what we've got now, bump it to current. |
5109
|
|
|
* |
5110
|
|
|
* @return bool: True if the option was incorrect and updated, false if nothing happened. |
|
|
|
|
5111
|
|
|
*/ |
5112
|
|
|
public static function maybe_set_version_option() { |
5113
|
|
|
list( $version ) = explode( ':', Jetpack_Options::get_option( 'version' ) ); |
5114
|
|
|
if ( JETPACK__VERSION != $version ) { |
5115
|
|
|
Jetpack_Options::update_option( 'version', JETPACK__VERSION . ':' . time() ); |
5116
|
|
|
return true; |
5117
|
|
|
} |
5118
|
|
|
return false; |
5119
|
|
|
} |
5120
|
|
|
|
5121
|
|
|
/* Client Server API */ |
5122
|
|
|
|
5123
|
|
|
/** |
5124
|
|
|
* Loads the Jetpack XML-RPC client |
5125
|
|
|
*/ |
5126
|
|
|
public static function load_xml_rpc_client() { |
5127
|
|
|
require_once ABSPATH . WPINC . '/class-IXR.php'; |
5128
|
|
|
require_once JETPACK__PLUGIN_DIR . 'class.jetpack-ixr-client.php'; |
5129
|
|
|
} |
5130
|
|
|
|
5131
|
|
|
function verify_xml_rpc_signature() { |
5132
|
|
|
if ( $this->xmlrpc_verification ) { |
5133
|
|
|
return $this->xmlrpc_verification; |
5134
|
|
|
} |
5135
|
|
|
|
5136
|
|
|
// It's not for us |
5137
|
|
|
if ( ! isset( $_GET['token'] ) || empty( $_GET['signature'] ) ) { |
5138
|
|
|
return false; |
5139
|
|
|
} |
5140
|
|
|
|
5141
|
|
|
@list( $token_key, $version, $user_id ) = explode( ':', $_GET['token'] ); |
|
|
|
|
5142
|
|
|
if ( |
5143
|
|
|
empty( $token_key ) |
5144
|
|
|
|| |
5145
|
|
|
empty( $version ) || strval( JETPACK__API_VERSION ) !== $version |
5146
|
|
|
) { |
5147
|
|
|
return false; |
5148
|
|
|
} |
5149
|
|
|
|
5150
|
|
|
if ( '0' === $user_id ) { |
5151
|
|
|
$token_type = 'blog'; |
5152
|
|
|
$user_id = 0; |
5153
|
|
|
} else { |
5154
|
|
|
$token_type = 'user'; |
5155
|
|
|
if ( empty( $user_id ) || ! ctype_digit( $user_id ) ) { |
5156
|
|
|
return false; |
5157
|
|
|
} |
5158
|
|
|
$user_id = (int) $user_id; |
5159
|
|
|
|
5160
|
|
|
$user = new WP_User( $user_id ); |
5161
|
|
|
if ( ! $user || ! $user->exists() ) { |
5162
|
|
|
return false; |
5163
|
|
|
} |
5164
|
|
|
} |
5165
|
|
|
|
5166
|
|
|
$token = Jetpack_Data::get_access_token( $user_id ); |
|
|
|
|
5167
|
|
|
if ( ! $token ) { |
5168
|
|
|
return false; |
5169
|
|
|
} |
5170
|
|
|
|
5171
|
|
|
$token_check = "$token_key."; |
5172
|
|
|
if ( ! hash_equals( substr( $token->secret, 0, strlen( $token_check ) ), $token_check ) ) { |
5173
|
|
|
return false; |
5174
|
|
|
} |
5175
|
|
|
|
5176
|
|
|
require_once JETPACK__PLUGIN_DIR . 'class.jetpack-signature.php'; |
5177
|
|
|
|
5178
|
|
|
$jetpack_signature = new Jetpack_Signature( $token->secret, (int) Jetpack_Options::get_option( 'time_diff' ) ); |
5179
|
|
|
if ( isset( $_POST['_jetpack_is_multipart'] ) ) { |
5180
|
|
|
$post_data = $_POST; |
5181
|
|
|
$file_hashes = array(); |
5182
|
|
|
foreach ( $post_data as $post_data_key => $post_data_value ) { |
5183
|
|
|
if ( 0 !== strpos( $post_data_key, '_jetpack_file_hmac_' ) ) { |
5184
|
|
|
continue; |
5185
|
|
|
} |
5186
|
|
|
$post_data_key = substr( $post_data_key, strlen( '_jetpack_file_hmac_' ) ); |
5187
|
|
|
$file_hashes[$post_data_key] = $post_data_value; |
5188
|
|
|
} |
5189
|
|
|
|
5190
|
|
|
foreach ( $file_hashes as $post_data_key => $post_data_value ) { |
5191
|
|
|
unset( $post_data["_jetpack_file_hmac_{$post_data_key}"] ); |
5192
|
|
|
$post_data[$post_data_key] = $post_data_value; |
5193
|
|
|
} |
5194
|
|
|
|
5195
|
|
|
ksort( $post_data ); |
5196
|
|
|
|
5197
|
|
|
$body = http_build_query( stripslashes_deep( $post_data ) ); |
5198
|
|
|
} elseif ( is_null( $this->HTTP_RAW_POST_DATA ) ) { |
5199
|
|
|
$body = file_get_contents( 'php://input' ); |
5200
|
|
|
} else { |
5201
|
|
|
$body = null; |
5202
|
|
|
} |
5203
|
|
|
$signature = $jetpack_signature->sign_current_request( |
5204
|
|
|
array( 'body' => is_null( $body ) ? $this->HTTP_RAW_POST_DATA : $body, ) |
5205
|
|
|
); |
5206
|
|
|
|
5207
|
|
|
if ( ! $signature ) { |
5208
|
|
|
return false; |
5209
|
|
|
} else if ( is_wp_error( $signature ) ) { |
5210
|
|
|
return $signature; |
5211
|
|
|
} else if ( ! hash_equals( $signature, $_GET['signature'] ) ) { |
5212
|
|
|
return false; |
5213
|
|
|
} |
5214
|
|
|
|
5215
|
|
|
$timestamp = (int) $_GET['timestamp']; |
5216
|
|
|
$nonce = stripslashes( (string) $_GET['nonce'] ); |
5217
|
|
|
|
5218
|
|
|
if ( ! $this->add_nonce( $timestamp, $nonce ) ) { |
5219
|
|
|
return false; |
5220
|
|
|
} |
5221
|
|
|
|
5222
|
|
|
$this->xmlrpc_verification = array( |
5223
|
|
|
'type' => $token_type, |
5224
|
|
|
'user_id' => $token->external_user_id, |
5225
|
|
|
); |
5226
|
|
|
|
5227
|
|
|
return $this->xmlrpc_verification; |
5228
|
|
|
} |
5229
|
|
|
|
5230
|
|
|
/** |
5231
|
|
|
* Authenticates XML-RPC and other requests from the Jetpack Server |
5232
|
|
|
*/ |
5233
|
|
|
function authenticate_jetpack( $user, $username, $password ) { |
|
|
|
|
5234
|
|
|
if ( is_a( $user, 'WP_User' ) ) { |
5235
|
|
|
return $user; |
5236
|
|
|
} |
5237
|
|
|
|
5238
|
|
|
$token_details = $this->verify_xml_rpc_signature(); |
5239
|
|
|
|
5240
|
|
|
if ( ! $token_details || is_wp_error( $token_details ) ) { |
5241
|
|
|
return $user; |
5242
|
|
|
} |
5243
|
|
|
|
5244
|
|
|
if ( 'user' !== $token_details['type'] ) { |
5245
|
|
|
return $user; |
5246
|
|
|
} |
5247
|
|
|
|
5248
|
|
|
if ( ! $token_details['user_id'] ) { |
5249
|
|
|
return $user; |
5250
|
|
|
} |
5251
|
|
|
|
5252
|
|
|
nocache_headers(); |
5253
|
|
|
|
5254
|
|
|
return new WP_User( $token_details['user_id'] ); |
5255
|
|
|
} |
5256
|
|
|
|
5257
|
|
|
function add_nonce( $timestamp, $nonce ) { |
5258
|
|
|
global $wpdb; |
5259
|
|
|
static $nonces_used_this_request = array(); |
5260
|
|
|
|
5261
|
|
|
if ( isset( $nonces_used_this_request["$timestamp:$nonce"] ) ) { |
5262
|
|
|
return $nonces_used_this_request["$timestamp:$nonce"]; |
5263
|
|
|
} |
5264
|
|
|
|
5265
|
|
|
// This should always have gone through Jetpack_Signature::sign_request() first to check $timestamp an $nonce |
5266
|
|
|
$timestamp = (int) $timestamp; |
5267
|
|
|
$nonce = esc_sql( $nonce ); |
5268
|
|
|
|
5269
|
|
|
// Raw query so we can avoid races: add_option will also update |
5270
|
|
|
$show_errors = $wpdb->show_errors( false ); |
5271
|
|
|
|
5272
|
|
|
$old_nonce = $wpdb->get_row( |
5273
|
|
|
$wpdb->prepare( "SELECT * FROM `$wpdb->options` WHERE option_name = %s", "jetpack_nonce_{$timestamp}_{$nonce}" ) |
5274
|
|
|
); |
5275
|
|
|
|
5276
|
|
|
if ( is_null( $old_nonce ) ) { |
5277
|
|
|
$return = $wpdb->query( |
5278
|
|
|
$wpdb->prepare( |
5279
|
|
|
"INSERT INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, %s)", |
5280
|
|
|
"jetpack_nonce_{$timestamp}_{$nonce}", |
5281
|
|
|
time(), |
5282
|
|
|
'no' |
5283
|
|
|
) |
5284
|
|
|
); |
5285
|
|
|
} else { |
5286
|
|
|
$return = false; |
5287
|
|
|
} |
5288
|
|
|
|
5289
|
|
|
$wpdb->show_errors( $show_errors ); |
5290
|
|
|
|
5291
|
|
|
$nonces_used_this_request["$timestamp:$nonce"] = $return; |
5292
|
|
|
|
5293
|
|
|
return $return; |
5294
|
|
|
} |
5295
|
|
|
|
5296
|
|
|
/** |
5297
|
|
|
* In some setups, $HTTP_RAW_POST_DATA can be emptied during some IXR_Server paths since it is passed by reference to various methods. |
5298
|
|
|
* Capture it here so we can verify the signature later. |
5299
|
|
|
*/ |
5300
|
|
|
function xmlrpc_methods( $methods ) { |
5301
|
|
|
$this->HTTP_RAW_POST_DATA = $GLOBALS['HTTP_RAW_POST_DATA']; |
5302
|
|
|
return $methods; |
5303
|
|
|
} |
5304
|
|
|
|
5305
|
|
|
function public_xmlrpc_methods( $methods ) { |
5306
|
|
|
if ( array_key_exists( 'wp.getOptions', $methods ) ) { |
5307
|
|
|
$methods['wp.getOptions'] = array( $this, 'jetpack_getOptions' ); |
5308
|
|
|
} |
5309
|
|
|
return $methods; |
5310
|
|
|
} |
5311
|
|
|
|
5312
|
|
|
function jetpack_getOptions( $args ) { |
5313
|
|
|
global $wp_xmlrpc_server; |
5314
|
|
|
|
5315
|
|
|
$wp_xmlrpc_server->escape( $args ); |
5316
|
|
|
|
5317
|
|
|
$username = $args[1]; |
5318
|
|
|
$password = $args[2]; |
5319
|
|
|
|
5320
|
|
|
if ( !$user = $wp_xmlrpc_server->login($username, $password) ) { |
5321
|
|
|
return $wp_xmlrpc_server->error; |
5322
|
|
|
} |
5323
|
|
|
|
5324
|
|
|
$options = array(); |
5325
|
|
|
$user_data = $this->get_connected_user_data(); |
5326
|
|
|
if ( is_array( $user_data ) ) { |
5327
|
|
|
$options['jetpack_user_id'] = array( |
5328
|
|
|
'desc' => __( 'The WP.com user ID of the connected user', 'jetpack' ), |
5329
|
|
|
'readonly' => true, |
5330
|
|
|
'value' => $user_data['ID'], |
5331
|
|
|
); |
5332
|
|
|
$options['jetpack_user_login'] = array( |
5333
|
|
|
'desc' => __( 'The WP.com username of the connected user', 'jetpack' ), |
5334
|
|
|
'readonly' => true, |
5335
|
|
|
'value' => $user_data['login'], |
5336
|
|
|
); |
5337
|
|
|
$options['jetpack_user_email'] = array( |
5338
|
|
|
'desc' => __( 'The WP.com user email of the connected user', 'jetpack' ), |
5339
|
|
|
'readonly' => true, |
5340
|
|
|
'value' => $user_data['email'], |
5341
|
|
|
); |
5342
|
|
|
$options['jetpack_user_site_count'] = array( |
5343
|
|
|
'desc' => __( 'The number of sites of the connected WP.com user', 'jetpack' ), |
5344
|
|
|
'readonly' => true, |
5345
|
|
|
'value' => $user_data['site_count'], |
5346
|
|
|
); |
5347
|
|
|
} |
5348
|
|
|
$wp_xmlrpc_server->blog_options = array_merge( $wp_xmlrpc_server->blog_options, $options ); |
5349
|
|
|
$args = stripslashes_deep( $args ); |
5350
|
|
|
return $wp_xmlrpc_server->wp_getOptions( $args ); |
5351
|
|
|
} |
5352
|
|
|
|
5353
|
|
|
function xmlrpc_options( $options ) { |
5354
|
|
|
$jetpack_client_id = false; |
5355
|
|
|
if ( self::is_active() ) { |
5356
|
|
|
$jetpack_client_id = Jetpack_Options::get_option( 'id' ); |
5357
|
|
|
} |
5358
|
|
|
$options['jetpack_version'] = array( |
5359
|
|
|
'desc' => __( 'Jetpack Plugin Version', 'jetpack' ), |
5360
|
|
|
'readonly' => true, |
5361
|
|
|
'value' => JETPACK__VERSION, |
5362
|
|
|
); |
5363
|
|
|
|
5364
|
|
|
$options['jetpack_client_id'] = array( |
5365
|
|
|
'desc' => __( 'The Client ID/WP.com Blog ID of this site', 'jetpack' ), |
5366
|
|
|
'readonly' => true, |
5367
|
|
|
'value' => $jetpack_client_id, |
5368
|
|
|
); |
5369
|
|
|
return $options; |
5370
|
|
|
} |
5371
|
|
|
|
5372
|
|
|
public static function clean_nonces( $all = false ) { |
5373
|
|
|
global $wpdb; |
5374
|
|
|
|
5375
|
|
|
$sql = "DELETE FROM `$wpdb->options` WHERE `option_name` LIKE %s"; |
5376
|
|
|
if ( method_exists ( $wpdb , 'esc_like' ) ) { |
5377
|
|
|
$sql_args = array( $wpdb->esc_like( 'jetpack_nonce_' ) . '%' ); |
5378
|
|
|
} else { |
5379
|
|
|
$sql_args = array( like_escape( 'jetpack_nonce_' ) . '%' ); |
5380
|
|
|
} |
5381
|
|
|
|
5382
|
|
|
if ( true !== $all ) { |
5383
|
|
|
$sql .= ' AND CAST( `option_value` AS UNSIGNED ) < %d'; |
5384
|
|
|
$sql_args[] = time() - 3600; |
5385
|
|
|
} |
5386
|
|
|
|
5387
|
|
|
$sql .= ' ORDER BY `option_id` LIMIT 100'; |
5388
|
|
|
|
5389
|
|
|
$sql = $wpdb->prepare( $sql, $sql_args ); |
5390
|
|
|
|
5391
|
|
|
for ( $i = 0; $i < 1000; $i++ ) { |
5392
|
|
|
if ( ! $wpdb->query( $sql ) ) { |
5393
|
|
|
break; |
5394
|
|
|
} |
5395
|
|
|
} |
5396
|
|
|
} |
5397
|
|
|
|
5398
|
|
|
/** |
5399
|
|
|
* State is passed via cookies from one request to the next, but never to subsequent requests. |
5400
|
|
|
* SET: state( $key, $value ); |
5401
|
|
|
* GET: $value = state( $key ); |
5402
|
|
|
* |
5403
|
|
|
* @param string $key |
|
|
|
|
5404
|
|
|
* @param string $value |
|
|
|
|
5405
|
|
|
* @param bool $restate private |
5406
|
|
|
*/ |
5407
|
|
|
public static function state( $key = null, $value = null, $restate = false ) { |
5408
|
|
|
static $state = array(); |
5409
|
|
|
static $path, $domain; |
5410
|
|
|
if ( ! isset( $path ) ) { |
5411
|
|
|
require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); |
5412
|
|
|
$admin_url = Jetpack::admin_url(); |
5413
|
|
|
$bits = parse_url( $admin_url ); |
5414
|
|
|
|
5415
|
|
|
if ( is_array( $bits ) ) { |
5416
|
|
|
$path = ( isset( $bits['path'] ) ) ? dirname( $bits['path'] ) : null; |
5417
|
|
|
$domain = ( isset( $bits['host'] ) ) ? $bits['host'] : null; |
5418
|
|
|
} else { |
5419
|
|
|
$path = $domain = null; |
5420
|
|
|
} |
5421
|
|
|
} |
5422
|
|
|
|
5423
|
|
|
// Extract state from cookies and delete cookies |
5424
|
|
|
if ( isset( $_COOKIE[ 'jetpackState' ] ) && is_array( $_COOKIE[ 'jetpackState' ] ) ) { |
5425
|
|
|
$yum = $_COOKIE[ 'jetpackState' ]; |
5426
|
|
|
unset( $_COOKIE[ 'jetpackState' ] ); |
5427
|
|
|
foreach ( $yum as $k => $v ) { |
5428
|
|
|
if ( strlen( $v ) ) |
5429
|
|
|
$state[ $k ] = $v; |
5430
|
|
|
setcookie( "jetpackState[$k]", false, 0, $path, $domain ); |
5431
|
|
|
} |
5432
|
|
|
} |
5433
|
|
|
|
5434
|
|
|
if ( $restate ) { |
5435
|
|
|
foreach ( $state as $k => $v ) { |
5436
|
|
|
setcookie( "jetpackState[$k]", $v, 0, $path, $domain ); |
5437
|
|
|
} |
5438
|
|
|
return; |
5439
|
|
|
} |
5440
|
|
|
|
5441
|
|
|
// Get a state variable |
5442
|
|
|
if ( isset( $key ) && ! isset( $value ) ) { |
5443
|
|
|
if ( array_key_exists( $key, $state ) ) |
5444
|
|
|
return $state[ $key ]; |
5445
|
|
|
return null; |
5446
|
|
|
} |
5447
|
|
|
|
5448
|
|
|
// Set a state variable |
5449
|
|
|
if ( isset ( $key ) && isset( $value ) ) { |
5450
|
|
|
if( is_array( $value ) && isset( $value[0] ) ) { |
5451
|
|
|
$value = $value[0]; |
5452
|
|
|
} |
5453
|
|
|
$state[ $key ] = $value; |
5454
|
|
|
setcookie( "jetpackState[$key]", $value, 0, $path, $domain ); |
5455
|
|
|
} |
5456
|
|
|
} |
5457
|
|
|
|
5458
|
|
|
public static function restate() { |
5459
|
|
|
Jetpack::state( null, null, true ); |
5460
|
|
|
} |
5461
|
|
|
|
5462
|
|
|
public static function check_privacy( $file ) { |
5463
|
|
|
static $is_site_publicly_accessible = null; |
5464
|
|
|
|
5465
|
|
|
if ( is_null( $is_site_publicly_accessible ) ) { |
5466
|
|
|
$is_site_publicly_accessible = false; |
5467
|
|
|
|
5468
|
|
|
Jetpack::load_xml_rpc_client(); |
5469
|
|
|
$rpc = new Jetpack_IXR_Client(); |
5470
|
|
|
|
5471
|
|
|
$success = $rpc->query( 'jetpack.isSitePubliclyAccessible', home_url() ); |
5472
|
|
|
if ( $success ) { |
5473
|
|
|
$response = $rpc->getResponse(); |
5474
|
|
|
if ( $response ) { |
5475
|
|
|
$is_site_publicly_accessible = true; |
5476
|
|
|
} |
5477
|
|
|
} |
5478
|
|
|
|
5479
|
|
|
Jetpack_Options::update_option( 'public', (int) $is_site_publicly_accessible ); |
5480
|
|
|
} |
5481
|
|
|
|
5482
|
|
|
if ( $is_site_publicly_accessible ) { |
5483
|
|
|
return; |
5484
|
|
|
} |
5485
|
|
|
|
5486
|
|
|
$module_slug = self::get_module_slug( $file ); |
5487
|
|
|
|
5488
|
|
|
$privacy_checks = Jetpack::state( 'privacy_checks' ); |
5489
|
|
|
if ( ! $privacy_checks ) { |
5490
|
|
|
$privacy_checks = $module_slug; |
5491
|
|
|
} else { |
5492
|
|
|
$privacy_checks .= ",$module_slug"; |
5493
|
|
|
} |
5494
|
|
|
|
5495
|
|
|
Jetpack::state( 'privacy_checks', $privacy_checks ); |
5496
|
|
|
} |
5497
|
|
|
|
5498
|
|
|
/** |
5499
|
|
|
* Helper method for multicall XMLRPC. |
5500
|
|
|
*/ |
5501
|
|
|
public static function xmlrpc_async_call() { |
5502
|
|
|
global $blog_id; |
5503
|
|
|
static $clients = array(); |
5504
|
|
|
|
5505
|
|
|
$client_blog_id = is_multisite() ? $blog_id : 0; |
5506
|
|
|
|
5507
|
|
|
if ( ! isset( $clients[$client_blog_id] ) ) { |
5508
|
|
|
Jetpack::load_xml_rpc_client(); |
5509
|
|
|
$clients[$client_blog_id] = new Jetpack_IXR_ClientMulticall( array( 'user_id' => JETPACK_MASTER_USER, ) ); |
5510
|
|
|
if ( function_exists( 'ignore_user_abort' ) ) { |
5511
|
|
|
ignore_user_abort( true ); |
5512
|
|
|
} |
5513
|
|
|
add_action( 'shutdown', array( 'Jetpack', 'xmlrpc_async_call' ) ); |
5514
|
|
|
} |
5515
|
|
|
|
5516
|
|
|
$args = func_get_args(); |
5517
|
|
|
|
5518
|
|
|
if ( ! empty( $args[0] ) ) { |
5519
|
|
|
call_user_func_array( array( $clients[$client_blog_id], 'addCall' ), $args ); |
5520
|
|
|
} elseif ( is_multisite() ) { |
5521
|
|
|
foreach ( $clients as $client_blog_id => $client ) { |
5522
|
|
|
if ( ! $client_blog_id || empty( $client->calls ) ) { |
5523
|
|
|
continue; |
5524
|
|
|
} |
5525
|
|
|
|
5526
|
|
|
$switch_success = switch_to_blog( $client_blog_id, true ); |
5527
|
|
|
if ( ! $switch_success ) { |
5528
|
|
|
continue; |
5529
|
|
|
} |
5530
|
|
|
|
5531
|
|
|
flush(); |
5532
|
|
|
$client->query(); |
5533
|
|
|
|
5534
|
|
|
restore_current_blog(); |
5535
|
|
|
} |
5536
|
|
|
} else { |
5537
|
|
|
if ( isset( $clients[0] ) && ! empty( $clients[0]->calls ) ) { |
5538
|
|
|
flush(); |
5539
|
|
|
$clients[0]->query(); |
5540
|
|
|
} |
5541
|
|
|
} |
5542
|
|
|
} |
5543
|
|
|
|
5544
|
|
|
public static function staticize_subdomain( $url ) { |
5545
|
|
|
|
5546
|
|
|
// Extract hostname from URL |
5547
|
|
|
$host = parse_url( $url, PHP_URL_HOST ); |
5548
|
|
|
|
5549
|
|
|
// Explode hostname on '.' |
5550
|
|
|
$exploded_host = explode( '.', $host ); |
5551
|
|
|
|
5552
|
|
|
// Retrieve the name and TLD |
5553
|
|
|
if ( count( $exploded_host ) > 1 ) { |
5554
|
|
|
$name = $exploded_host[ count( $exploded_host ) - 2 ]; |
5555
|
|
|
$tld = $exploded_host[ count( $exploded_host ) - 1 ]; |
5556
|
|
|
// Rebuild domain excluding subdomains |
5557
|
|
|
$domain = $name . '.' . $tld; |
5558
|
|
|
} else { |
5559
|
|
|
$domain = $host; |
5560
|
|
|
} |
5561
|
|
|
// Array of Automattic domains |
5562
|
|
|
$domain_whitelist = array( 'wordpress.com', 'wp.com' ); |
5563
|
|
|
|
5564
|
|
|
// Return $url if not an Automattic domain |
5565
|
|
|
if ( ! in_array( $domain, $domain_whitelist ) ) { |
5566
|
|
|
return $url; |
5567
|
|
|
} |
5568
|
|
|
|
5569
|
|
|
if ( is_ssl() ) { |
5570
|
|
|
return preg_replace( '|https?://[^/]++/|', 'https://s-ssl.wordpress.com/', $url ); |
5571
|
|
|
} |
5572
|
|
|
|
5573
|
|
|
srand( crc32( basename( $url ) ) ); |
5574
|
|
|
$static_counter = rand( 0, 2 ); |
5575
|
|
|
srand(); // this resets everything that relies on this, like array_rand() and shuffle() |
5576
|
|
|
|
5577
|
|
|
return preg_replace( '|://[^/]+?/|', "://s$static_counter.wp.com/", $url ); |
5578
|
|
|
} |
5579
|
|
|
|
5580
|
|
|
/* JSON API Authorization */ |
5581
|
|
|
|
5582
|
|
|
/** |
5583
|
|
|
* Handles the login action for Authorizing the JSON API |
5584
|
|
|
*/ |
5585
|
|
|
function login_form_json_api_authorization() { |
5586
|
|
|
$this->verify_json_api_authorization_request(); |
5587
|
|
|
|
5588
|
|
|
add_action( 'wp_login', array( &$this, 'store_json_api_authorization_token' ), 10, 2 ); |
5589
|
|
|
|
5590
|
|
|
add_action( 'login_message', array( &$this, 'login_message_json_api_authorization' ) ); |
5591
|
|
|
add_action( 'login_form', array( &$this, 'preserve_action_in_login_form_for_json_api_authorization' ) ); |
5592
|
|
|
add_filter( 'site_url', array( &$this, 'post_login_form_to_signed_url' ), 10, 3 ); |
5593
|
|
|
} |
5594
|
|
|
|
5595
|
|
|
// Make sure the login form is POSTed to the signed URL so we can reverify the request |
5596
|
|
|
function post_login_form_to_signed_url( $url, $path, $scheme ) { |
5597
|
|
|
if ( 'wp-login.php' !== $path || ( 'login_post' !== $scheme && 'login' !== $scheme ) ) { |
5598
|
|
|
return $url; |
5599
|
|
|
} |
5600
|
|
|
|
5601
|
|
|
$parsed_url = parse_url( $url ); |
5602
|
|
|
$url = strtok( $url, '?' ); |
5603
|
|
|
$url = "$url?{$_SERVER['QUERY_STRING']}"; |
5604
|
|
|
if ( ! empty( $parsed_url['query'] ) ) |
5605
|
|
|
$url .= "&{$parsed_url['query']}"; |
5606
|
|
|
|
5607
|
|
|
return $url; |
5608
|
|
|
} |
5609
|
|
|
|
5610
|
|
|
// Make sure the POSTed request is handled by the same action |
5611
|
|
|
function preserve_action_in_login_form_for_json_api_authorization() { |
5612
|
|
|
echo "<input type='hidden' name='action' value='jetpack_json_api_authorization' />\n"; |
5613
|
|
|
echo "<input type='hidden' name='jetpack_json_api_original_query' value='" . esc_url( set_url_scheme( $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ) ) . "' />\n"; |
5614
|
|
|
} |
5615
|
|
|
|
5616
|
|
|
// If someone logs in to approve API access, store the Access Code in usermeta |
5617
|
|
|
function store_json_api_authorization_token( $user_login, $user ) { |
5618
|
|
|
add_filter( 'login_redirect', array( &$this, 'add_token_to_login_redirect_json_api_authorization' ), 10, 3 ); |
5619
|
|
|
add_filter( 'allowed_redirect_hosts', array( &$this, 'allow_wpcom_public_api_domain' ) ); |
5620
|
|
|
$token = wp_generate_password( 32, false ); |
5621
|
|
|
update_user_meta( $user->ID, 'jetpack_json_api_' . $this->json_api_authorization_request['client_id'], $token ); |
5622
|
|
|
} |
5623
|
|
|
|
5624
|
|
|
// Add public-api.wordpress.com to the safe redirect whitelist - only added when someone allows API access |
5625
|
|
|
function allow_wpcom_public_api_domain( $domains ) { |
5626
|
|
|
$domains[] = 'public-api.wordpress.com'; |
5627
|
|
|
return $domains; |
5628
|
|
|
} |
5629
|
|
|
|
5630
|
|
|
// Add the Access Code details to the public-api.wordpress.com redirect |
5631
|
|
|
function add_token_to_login_redirect_json_api_authorization( $redirect_to, $original_redirect_to, $user ) { |
5632
|
|
|
return add_query_arg( |
5633
|
|
|
urlencode_deep( |
5634
|
|
|
array( |
5635
|
|
|
'jetpack-code' => get_user_meta( $user->ID, 'jetpack_json_api_' . $this->json_api_authorization_request['client_id'], true ), |
5636
|
|
|
'jetpack-user-id' => (int) $user->ID, |
5637
|
|
|
'jetpack-state' => $this->json_api_authorization_request['state'], |
5638
|
|
|
) |
5639
|
|
|
), |
5640
|
|
|
$redirect_to |
5641
|
|
|
); |
5642
|
|
|
} |
5643
|
|
|
|
5644
|
|
|
// Verifies the request by checking the signature |
5645
|
|
|
function verify_json_api_authorization_request() { |
5646
|
|
|
require_once JETPACK__PLUGIN_DIR . 'class.jetpack-signature.php'; |
5647
|
|
|
|
5648
|
|
|
$token = Jetpack_Data::get_access_token( JETPACK_MASTER_USER ); |
5649
|
|
|
if ( ! $token || empty( $token->secret ) ) { |
5650
|
|
|
wp_die( __( 'You must connect your Jetpack plugin to WordPress.com to use this feature.' , 'jetpack' ) ); |
5651
|
|
|
} |
5652
|
|
|
|
5653
|
|
|
$die_error = __( 'Someone may be trying to trick you into giving them access to your site. Or it could be you just encountered a bug :). Either way, please close this window.', 'jetpack' ); |
5654
|
|
|
|
5655
|
|
|
$jetpack_signature = new Jetpack_Signature( $token->secret, (int) Jetpack_Options::get_option( 'time_diff' ) ); |
5656
|
|
|
|
5657
|
|
|
if ( isset( $_POST['jetpack_json_api_original_query'] ) ) { |
5658
|
|
|
$signature = $jetpack_signature->sign_request( $_GET['token'], $_GET['timestamp'], $_GET['nonce'], '', 'GET', $_POST['jetpack_json_api_original_query'], null, true ); |
5659
|
|
|
} else { |
5660
|
|
|
$signature = $jetpack_signature->sign_current_request( array( 'body' => null, 'method' => 'GET' ) ); |
5661
|
|
|
} |
5662
|
|
|
|
5663
|
|
|
if ( ! $signature ) { |
5664
|
|
|
wp_die( $die_error ); |
5665
|
|
|
} else if ( is_wp_error( $signature ) ) { |
5666
|
|
|
wp_die( $die_error ); |
5667
|
|
|
} else if ( $signature !== $_GET['signature'] ) { |
5668
|
|
|
if ( is_ssl() ) { |
5669
|
|
|
// If we signed an HTTP request on the Jetpack Servers, but got redirected to HTTPS by the local blog, check the HTTP signature as well |
5670
|
|
|
$signature = $jetpack_signature->sign_current_request( array( 'scheme' => 'http', 'body' => null, 'method' => 'GET' ) ); |
5671
|
|
|
if ( ! $signature || is_wp_error( $signature ) || $signature !== $_GET['signature'] ) { |
5672
|
|
|
wp_die( $die_error ); |
5673
|
|
|
} |
5674
|
|
|
} else { |
5675
|
|
|
wp_die( $die_error ); |
5676
|
|
|
} |
5677
|
|
|
} |
5678
|
|
|
|
5679
|
|
|
$timestamp = (int) $_GET['timestamp']; |
5680
|
|
|
$nonce = stripslashes( (string) $_GET['nonce'] ); |
5681
|
|
|
|
5682
|
|
|
if ( ! $this->add_nonce( $timestamp, $nonce ) ) { |
5683
|
|
|
// De-nonce the nonce, at least for 5 minutes. |
5684
|
|
|
// We have to reuse this nonce at least once (used the first time when the initial request is made, used a second time when the login form is POSTed) |
5685
|
|
|
$old_nonce_time = get_option( "jetpack_nonce_{$timestamp}_{$nonce}" ); |
5686
|
|
|
if ( $old_nonce_time < time() - 300 ) { |
5687
|
|
|
wp_die( __( 'The authorization process expired. Please go back and try again.' , 'jetpack' ) ); |
5688
|
|
|
} |
5689
|
|
|
} |
5690
|
|
|
|
5691
|
|
|
$data = json_decode( base64_decode( stripslashes( $_GET['data'] ) ) ); |
5692
|
|
|
$data_filters = array( |
5693
|
|
|
'state' => 'opaque', |
5694
|
|
|
'client_id' => 'int', |
5695
|
|
|
'client_title' => 'string', |
5696
|
|
|
'client_image' => 'url', |
5697
|
|
|
); |
5698
|
|
|
|
5699
|
|
|
foreach ( $data_filters as $key => $sanitation ) { |
5700
|
|
|
if ( ! isset( $data->$key ) ) { |
5701
|
|
|
wp_die( $die_error ); |
5702
|
|
|
} |
5703
|
|
|
|
5704
|
|
|
switch ( $sanitation ) { |
5705
|
|
|
case 'int' : |
5706
|
|
|
$this->json_api_authorization_request[$key] = (int) $data->$key; |
5707
|
|
|
break; |
5708
|
|
|
case 'opaque' : |
5709
|
|
|
$this->json_api_authorization_request[$key] = (string) $data->$key; |
5710
|
|
|
break; |
5711
|
|
|
case 'string' : |
5712
|
|
|
$this->json_api_authorization_request[$key] = wp_kses( (string) $data->$key, array() ); |
5713
|
|
|
break; |
5714
|
|
|
case 'url' : |
5715
|
|
|
$this->json_api_authorization_request[$key] = esc_url_raw( (string) $data->$key ); |
5716
|
|
|
break; |
5717
|
|
|
} |
5718
|
|
|
} |
5719
|
|
|
|
5720
|
|
|
if ( empty( $this->json_api_authorization_request['client_id'] ) ) { |
5721
|
|
|
wp_die( $die_error ); |
5722
|
|
|
} |
5723
|
|
|
} |
5724
|
|
|
|
5725
|
|
|
function login_message_json_api_authorization( $message ) { |
|
|
|
|
5726
|
|
|
return '<p class="message">' . sprintf( |
5727
|
|
|
esc_html__( '%s wants to access your site’s data. Log in to authorize that access.' , 'jetpack' ), |
5728
|
|
|
'<strong>' . esc_html( $this->json_api_authorization_request['client_title'] ) . '</strong>' |
5729
|
|
|
) . '<img src="' . esc_url( $this->json_api_authorization_request['client_image'] ) . '" /></p>'; |
5730
|
|
|
} |
5731
|
|
|
|
5732
|
|
|
/** |
5733
|
|
|
* Get $content_width, but with a <s>twist</s> filter. |
5734
|
|
|
*/ |
5735
|
|
|
public static function get_content_width() { |
5736
|
|
|
$content_width = isset( $GLOBALS['content_width'] ) ? $GLOBALS['content_width'] : false; |
5737
|
|
|
/** |
5738
|
|
|
* Filter the Content Width value. |
5739
|
|
|
* |
5740
|
|
|
* @since 2.2.3 |
5741
|
|
|
* |
5742
|
|
|
* @param string $content_width Content Width value. |
5743
|
|
|
*/ |
5744
|
|
|
return apply_filters( 'jetpack_content_width', $content_width ); |
5745
|
|
|
} |
5746
|
|
|
|
5747
|
|
|
/** |
5748
|
|
|
* Centralize the function here until it gets added to core. |
5749
|
|
|
* |
5750
|
|
|
* @param int|string|object $id_or_email A user ID, email address, or comment object |
5751
|
|
|
* @param int $size Size of the avatar image |
5752
|
|
|
* @param string $default URL to a default image to use if no avatar is available |
5753
|
|
|
* @param bool $force_display Whether to force it to return an avatar even if show_avatars is disabled |
5754
|
|
|
* |
5755
|
|
|
* @return array First element is the URL, second is the class. |
5756
|
|
|
*/ |
5757
|
|
|
public static function get_avatar_url( $id_or_email, $size = 96, $default = '', $force_display = false ) { |
5758
|
|
|
// Don't bother adding the __return_true filter if it's already there. |
5759
|
|
|
$has_filter = has_filter( 'pre_option_show_avatars', '__return_true' ); |
5760
|
|
|
|
5761
|
|
|
if ( $force_display && ! $has_filter ) |
5762
|
|
|
add_filter( 'pre_option_show_avatars', '__return_true' ); |
5763
|
|
|
|
5764
|
|
|
$avatar = get_avatar( $id_or_email, $size, $default ); |
5765
|
|
|
|
5766
|
|
|
if ( $force_display && ! $has_filter ) |
5767
|
|
|
remove_filter( 'pre_option_show_avatars', '__return_true' ); |
5768
|
|
|
|
5769
|
|
|
// If no data, fail out. |
5770
|
|
|
if ( is_wp_error( $avatar ) || ! $avatar ) |
5771
|
|
|
return array( null, null ); |
5772
|
|
|
|
5773
|
|
|
// Pull out the URL. If it's not there, fail out. |
5774
|
|
|
if ( ! preg_match( '/src=["\']([^"\']+)["\']/', $avatar, $url_matches ) ) |
5775
|
|
|
return array( null, null ); |
5776
|
|
|
$url = wp_specialchars_decode( $url_matches[1], ENT_QUOTES ); |
5777
|
|
|
|
5778
|
|
|
// Pull out the class, but it's not a big deal if it's missing. |
5779
|
|
|
$class = ''; |
5780
|
|
|
if ( preg_match( '/class=["\']([^"\']+)["\']/', $avatar, $class_matches ) ) |
5781
|
|
|
$class = wp_specialchars_decode( $class_matches[1], ENT_QUOTES ); |
5782
|
|
|
|
5783
|
|
|
return array( $url, $class ); |
5784
|
|
|
} |
5785
|
|
|
|
5786
|
|
|
/** |
5787
|
|
|
* Pings the WordPress.com Mirror Site for the specified options. |
5788
|
|
|
* |
5789
|
|
|
* @param string|array $option_names The option names to request from the WordPress.com Mirror Site |
5790
|
|
|
* |
5791
|
|
|
* @return array An associative array of the option values as stored in the WordPress.com Mirror Site |
5792
|
|
|
*/ |
5793
|
|
|
public function get_cloud_site_options( $option_names ) { |
5794
|
|
|
$option_names = array_filter( (array) $option_names, 'is_string' ); |
5795
|
|
|
|
5796
|
|
|
Jetpack::load_xml_rpc_client(); |
5797
|
|
|
$xml = new Jetpack_IXR_Client( array( 'user_id' => JETPACK_MASTER_USER, ) ); |
5798
|
|
|
$xml->query( 'jetpack.fetchSiteOptions', $option_names ); |
5799
|
|
|
if ( $xml->isError() ) { |
5800
|
|
|
return array( |
5801
|
|
|
'error_code' => $xml->getErrorCode(), |
5802
|
|
|
'error_msg' => $xml->getErrorMessage(), |
5803
|
|
|
); |
5804
|
|
|
} |
5805
|
|
|
$cloud_site_options = $xml->getResponse(); |
5806
|
|
|
|
5807
|
|
|
return $cloud_site_options; |
5808
|
|
|
} |
5809
|
|
|
|
5810
|
|
|
/** |
5811
|
|
|
* Fetch the filtered array of options that we should compare to determine an identity crisis. |
5812
|
|
|
* |
5813
|
|
|
* @return array An array of options to check. |
5814
|
|
|
*/ |
5815
|
|
|
public static function identity_crisis_options_to_check() { |
5816
|
|
|
$options = array( |
5817
|
|
|
'siteurl', |
5818
|
|
|
'home', |
5819
|
|
|
); |
5820
|
|
|
/** |
5821
|
|
|
* Filter the options that we should compare to determine an identity crisis. |
5822
|
|
|
* |
5823
|
|
|
* @since 2.5.0 |
5824
|
|
|
* |
5825
|
|
|
* @param array $options Array of options to compare to determine an identity crisis. |
5826
|
|
|
*/ |
5827
|
|
|
return apply_filters( 'jetpack_identity_crisis_options_to_check', $options ); |
5828
|
|
|
} |
5829
|
|
|
|
5830
|
|
|
/** |
5831
|
|
|
* Checks to make sure that local options have the same values as remote options. Will cache the results for up to 24 hours. |
5832
|
|
|
* |
5833
|
|
|
* @param bool $force_recheck Whether to ignore any cached transient and manually re-check. |
5834
|
|
|
* |
5835
|
|
|
* @return array An array of options that do not match. If everything is good, it will evaluate to false. |
5836
|
|
|
*/ |
5837
|
|
|
public static function check_identity_crisis( $force_recheck = false ) { |
5838
|
|
|
if ( ! Jetpack::is_active() || Jetpack::is_development_mode() || Jetpack::is_staging_site() ) |
5839
|
|
|
return false; |
5840
|
|
|
|
5841
|
|
|
if ( $force_recheck || false === ( $errors = get_transient( 'jetpack_has_identity_crisis' ) ) ) { |
5842
|
|
|
$options_to_check = self::identity_crisis_options_to_check(); |
5843
|
|
|
$cloud_options = Jetpack::init()->get_cloud_site_options( $options_to_check ); |
5844
|
|
|
$errors = array(); |
5845
|
|
|
|
5846
|
|
|
foreach ( $cloud_options as $cloud_key => $cloud_value ) { |
5847
|
|
|
|
5848
|
|
|
// If it's not the same as the local value... |
5849
|
|
|
if ( $cloud_value !== get_option( $cloud_key ) ) { |
5850
|
|
|
|
5851
|
|
|
// Break out if we're getting errors. We are going to check the error keys later when we alert. |
5852
|
|
|
if ( 'error_code' == $cloud_key ) { |
5853
|
|
|
$errors[ $cloud_key ] = $cloud_value; |
5854
|
|
|
break; |
5855
|
|
|
} |
5856
|
|
|
|
5857
|
|
|
$parsed_cloud_value = parse_url( $cloud_value ); |
5858
|
|
|
// If the current options is an IP address |
5859
|
|
|
if ( filter_var( $parsed_cloud_value['host'], FILTER_VALIDATE_IP ) ) { |
5860
|
|
|
// Give the new value a Jetpack to fly in to the clouds |
5861
|
|
|
Jetpack::resolve_identity_crisis( $cloud_key ); |
5862
|
|
|
continue; |
5863
|
|
|
} |
5864
|
|
|
|
5865
|
|
|
// And it's not been added to the whitelist... |
5866
|
|
|
if ( ! self::is_identity_crisis_value_whitelisted( $cloud_key, $cloud_value ) ) { |
5867
|
|
|
/* |
5868
|
|
|
* This should be a temporary hack until a cleaner solution is found. |
5869
|
|
|
* |
5870
|
|
|
* The siteurl and home can be set to use http in General > Settings |
5871
|
|
|
* however some constants can be defined that can force https in wp-admin |
5872
|
|
|
* when this happens wpcom can confuse wporg with a fake identity |
5873
|
|
|
* crisis with a mismatch of http vs https when it should be allowed. |
5874
|
|
|
* we need to check that here. |
5875
|
|
|
* |
5876
|
|
|
* @see https://github.com/Automattic/jetpack/issues/1006 |
5877
|
|
|
*/ |
5878
|
|
|
if ( ( 'home' == $cloud_key || 'siteurl' == $cloud_key ) |
5879
|
|
|
&& ( substr( $cloud_value, 0, 8 ) == "https://" ) |
5880
|
|
|
&& Jetpack::init()->is_ssl_required_to_visit_site() ) { |
5881
|
|
|
// Ok, we found a mismatch of http and https because of wp-config, not an invalid url |
5882
|
|
|
continue; |
5883
|
|
|
} |
5884
|
|
|
|
5885
|
|
|
|
5886
|
|
|
// Then kick an error! |
5887
|
|
|
$errors[ $cloud_key ] = $cloud_value; |
5888
|
|
|
} |
5889
|
|
|
} |
5890
|
|
|
} |
5891
|
|
|
} |
5892
|
|
|
|
5893
|
|
|
/** |
5894
|
|
|
* Filters the errors returned when checking for an Identity Crisis. |
5895
|
|
|
* |
5896
|
|
|
* @since 2.3.2 |
5897
|
|
|
* |
5898
|
|
|
* @param array $errors Array of Identity Crisis errors. |
5899
|
|
|
* @param bool $force_recheck Ignore any cached transient and manually re-check. Default to false. |
5900
|
|
|
*/ |
5901
|
|
|
return apply_filters( 'jetpack_has_identity_crisis', $errors, $force_recheck ); |
5902
|
|
|
} |
5903
|
|
|
|
5904
|
|
|
/* |
5905
|
|
|
* Resolve ID crisis |
5906
|
|
|
* |
5907
|
|
|
* If the URL has changed, but the rest of the options are the same (i.e. blog/user tokens) |
5908
|
|
|
* The user has the option to update the shadow site with the new URL before a new |
5909
|
|
|
* token is created. |
5910
|
|
|
* |
5911
|
|
|
* @param $key : Which option to sync. null defautlts to home and siteurl |
5912
|
|
|
*/ |
5913
|
|
|
public static function resolve_identity_crisis( $key = null ) { |
5914
|
|
|
if ( $key ) { |
5915
|
|
|
$identity_options = array( $key ); |
5916
|
|
|
} else { |
5917
|
|
|
$identity_options = self::identity_crisis_options_to_check(); |
5918
|
|
|
} |
5919
|
|
|
|
5920
|
|
|
if ( is_array( $identity_options ) ) { |
5921
|
|
|
foreach( $identity_options as $identity_option ) { |
5922
|
|
|
Jetpack_Sync::sync_options( __FILE__, $identity_option ); |
5923
|
|
|
|
5924
|
|
|
/** |
5925
|
|
|
* Fires when a shadow site option is updated. |
5926
|
|
|
* These options are updated via the Identity Crisis UI. |
5927
|
|
|
* $identity_option is the option that gets updated. |
5928
|
|
|
* |
5929
|
|
|
* @since 3.7.0 |
5930
|
|
|
*/ |
5931
|
|
|
do_action( "update_option_{$identity_option}" ); |
5932
|
|
|
} |
5933
|
|
|
} |
5934
|
|
|
} |
5935
|
|
|
|
5936
|
|
|
/* |
5937
|
|
|
* Whitelist URL |
5938
|
|
|
* |
5939
|
|
|
* Ignore the URL differences between the blog and the shadow site. |
5940
|
|
|
*/ |
5941
|
|
|
public static function whitelist_current_url() { |
5942
|
|
|
$options_to_check = Jetpack::identity_crisis_options_to_check(); |
5943
|
|
|
$cloud_options = Jetpack::init()->get_cloud_site_options( $options_to_check ); |
5944
|
|
|
|
5945
|
|
|
foreach ( $cloud_options as $cloud_key => $cloud_value ) { |
5946
|
|
|
Jetpack::whitelist_identity_crisis_value( $cloud_key, $cloud_value ); |
5947
|
|
|
} |
5948
|
|
|
} |
5949
|
|
|
|
5950
|
|
|
/* |
5951
|
|
|
* Ajax callbacks for ID crisis resolutions |
5952
|
|
|
* |
5953
|
|
|
* Things that could happen here: |
5954
|
|
|
* - site_migrated : Update the URL on the shadow blog to match new domain |
5955
|
|
|
* - whitelist : Ignore the URL difference |
5956
|
|
|
* - default : Error message |
5957
|
|
|
*/ |
5958
|
|
|
public static function resolve_identity_crisis_ajax_callback() { |
5959
|
|
|
check_ajax_referer( 'resolve-identity-crisis', 'ajax-nonce' ); |
5960
|
|
|
|
5961
|
|
|
switch ( $_POST[ 'crisis_resolution_action' ] ) { |
5962
|
|
|
case 'site_migrated': |
5963
|
|
|
Jetpack::resolve_identity_crisis(); |
5964
|
|
|
echo 'resolved'; |
5965
|
|
|
break; |
5966
|
|
|
|
5967
|
|
|
case 'whitelist': |
5968
|
|
|
Jetpack::whitelist_current_url(); |
5969
|
|
|
echo 'whitelisted'; |
5970
|
|
|
break; |
5971
|
|
|
|
5972
|
|
|
case 'reset_connection': |
5973
|
|
|
// Delete the options first so it doesn't get confused which site to disconnect dotcom-side |
5974
|
|
|
Jetpack_Options::delete_option( |
5975
|
|
|
array( |
5976
|
|
|
'register', |
5977
|
|
|
'blog_token', |
5978
|
|
|
'user_token', |
5979
|
|
|
'user_tokens', |
5980
|
|
|
'master_user', |
5981
|
|
|
'time_diff', |
5982
|
|
|
'fallback_no_verify_ssl_certs', |
5983
|
|
|
'id', |
5984
|
|
|
) |
5985
|
|
|
); |
5986
|
|
|
delete_transient( 'jetpack_has_identity_crisis' ); |
5987
|
|
|
|
5988
|
|
|
echo 'reset-connection-success'; |
5989
|
|
|
break; |
5990
|
|
|
|
5991
|
|
|
default: |
5992
|
|
|
echo 'missing action'; |
5993
|
|
|
break; |
5994
|
|
|
} |
5995
|
|
|
|
5996
|
|
|
wp_die(); |
5997
|
|
|
} |
5998
|
|
|
|
5999
|
|
|
/** |
6000
|
|
|
* Adds a value to the whitelist for the specified key. |
6001
|
|
|
* |
6002
|
|
|
* @param string $key The option name that we're whitelisting the value for. |
6003
|
|
|
* @param string $value The value that we're intending to add to the whitelist. |
6004
|
|
|
* |
6005
|
|
|
* @return bool Whether the value was added to the whitelist, or false if it was already there. |
6006
|
|
|
*/ |
6007
|
|
|
public static function whitelist_identity_crisis_value( $key, $value ) { |
6008
|
|
|
if ( Jetpack::is_identity_crisis_value_whitelisted( $key, $value ) ) { |
6009
|
|
|
return false; |
6010
|
|
|
} |
6011
|
|
|
|
6012
|
|
|
$whitelist = Jetpack_Options::get_option( 'identity_crisis_whitelist', array() ); |
6013
|
|
|
if ( empty( $whitelist[ $key ] ) || ! is_array( $whitelist[ $key ] ) ) { |
6014
|
|
|
$whitelist[ $key ] = array(); |
6015
|
|
|
} |
6016
|
|
|
array_push( $whitelist[ $key ], $value ); |
6017
|
|
|
|
6018
|
|
|
Jetpack_Options::update_option( 'identity_crisis_whitelist', $whitelist ); |
6019
|
|
|
return true; |
6020
|
|
|
} |
6021
|
|
|
|
6022
|
|
|
/** |
6023
|
|
|
* Checks whether a value is already whitelisted. |
6024
|
|
|
* |
6025
|
|
|
* @param string $key The option name that we're checking the value for. |
6026
|
|
|
* @param string $value The value that we're curious to see if it's on the whitelist. |
6027
|
|
|
* |
6028
|
|
|
* @return bool Whether the value is whitelisted. |
6029
|
|
|
*/ |
6030
|
|
|
public static function is_identity_crisis_value_whitelisted( $key, $value ) { |
6031
|
|
|
$whitelist = Jetpack_Options::get_option( 'identity_crisis_whitelist', array() ); |
6032
|
|
|
if ( ! empty( $whitelist[ $key ] ) && is_array( $whitelist[ $key ] ) && in_array( $value, $whitelist[ $key ] ) ) { |
6033
|
|
|
return true; |
6034
|
|
|
} |
6035
|
|
|
return false; |
6036
|
|
|
} |
6037
|
|
|
|
6038
|
|
|
/** |
6039
|
|
|
* Checks whether the home and siteurl specifically are whitelisted |
6040
|
|
|
* Written so that we don't have re-check $key and $value params every time |
6041
|
|
|
* we want to check if this site is whitelisted, for example in footer.php |
6042
|
|
|
* |
6043
|
|
|
* @return bool True = already whitelsisted False = not whitelisted |
6044
|
|
|
*/ |
6045
|
|
|
public static function is_staging_site() { |
6046
|
|
|
$is_staging = false; |
6047
|
|
|
|
6048
|
|
|
$current_whitelist = Jetpack_Options::get_option( 'identity_crisis_whitelist' ); |
6049
|
|
|
if ( $current_whitelist ) { |
6050
|
|
|
$options_to_check = Jetpack::identity_crisis_options_to_check(); |
6051
|
|
|
$cloud_options = Jetpack::init()->get_cloud_site_options( $options_to_check ); |
6052
|
|
|
|
6053
|
|
|
foreach ( $cloud_options as $cloud_key => $cloud_value ) { |
6054
|
|
|
if ( self::is_identity_crisis_value_whitelisted( $cloud_key, $cloud_value ) ) { |
6055
|
|
|
$is_staging = true; |
6056
|
|
|
break; |
6057
|
|
|
} |
6058
|
|
|
} |
6059
|
|
|
} |
6060
|
|
|
$known_staging = array( |
6061
|
|
|
'urls' => array( |
6062
|
|
|
'#\.staging\.wpengine\.com$#i', |
6063
|
|
|
), |
6064
|
|
|
'constants' => array( |
6065
|
|
|
'IS_WPE_SNAPSHOT', |
6066
|
|
|
'JETPACK_STAGING_MODE', |
6067
|
|
|
) |
6068
|
|
|
); |
6069
|
|
|
/** |
6070
|
|
|
* Filters the flags of known staging sites. |
6071
|
|
|
* |
6072
|
|
|
* @since 3.9.0 |
6073
|
|
|
* |
6074
|
|
|
* @param array $known_staging { |
6075
|
|
|
* An array of arrays that each are used to check if the current site is staging. |
6076
|
|
|
* @type array $urls URLs of staging sites in regex to check against site_url. |
6077
|
|
|
* @type array $cosntants PHP constants of known staging/developement environments. |
6078
|
|
|
* } |
6079
|
|
|
*/ |
6080
|
|
|
$known_staging = apply_filters( 'jetpack_known_staging', $known_staging ); |
6081
|
|
|
|
6082
|
|
|
if ( isset( $known_staging['urls'] ) ) { |
6083
|
|
|
foreach ( $known_staging['urls'] as $url ){ |
6084
|
|
|
if ( preg_match( $url, site_url() ) ) { |
6085
|
|
|
$is_staging = true; |
6086
|
|
|
break; |
6087
|
|
|
} |
6088
|
|
|
} |
6089
|
|
|
} |
6090
|
|
|
|
6091
|
|
|
if ( isset( $known_staging['constants'] ) ) { |
6092
|
|
|
foreach ( $known_staging['constants'] as $constant ) { |
6093
|
|
|
if ( defined( $constant ) && constant( $constant ) ) { |
6094
|
|
|
$is_staging = true; |
6095
|
|
|
} |
6096
|
|
|
} |
6097
|
|
|
} |
6098
|
|
|
|
6099
|
|
|
/** |
6100
|
|
|
* Filters is_staging_site check. |
6101
|
|
|
* |
6102
|
|
|
* @since 3.9.0 |
6103
|
|
|
* |
6104
|
|
|
* @param bool $is_staging If the current site is a staging site. |
6105
|
|
|
*/ |
6106
|
|
|
return apply_filters( 'jetpack_is_staging_site', $is_staging ); |
6107
|
|
|
} |
6108
|
|
|
|
6109
|
|
|
public function identity_crisis_js( $nonce ) { |
6110
|
|
|
?> |
6111
|
|
|
<script> |
6112
|
|
|
(function( $ ) { |
6113
|
|
|
var SECOND_IN_MS = 1000; |
6114
|
|
|
|
6115
|
|
|
function contactSupport( e ) { |
6116
|
|
|
e.preventDefault(); |
6117
|
|
|
$( '.jp-id-crisis-question' ).hide(); |
6118
|
|
|
$( '#jp-id-crisis-contact-support' ).show(); |
6119
|
|
|
} |
6120
|
|
|
|
6121
|
|
|
function autodismissSuccessBanner() { |
6122
|
|
|
$( '.jp-identity-crisis' ).fadeOut(600); //.addClass( 'dismiss' ); |
6123
|
|
|
} |
6124
|
|
|
|
6125
|
|
|
var data = { action: 'jetpack_resolve_identity_crisis', 'ajax-nonce': '<?php echo $nonce; ?>' }; |
6126
|
|
|
|
6127
|
|
|
$( document ).ready(function() { |
6128
|
|
|
|
6129
|
|
|
// Site moved: Update the URL on the shadow blog |
6130
|
|
|
$( '.site-moved' ).click(function( e ) { |
6131
|
|
|
e.preventDefault(); |
6132
|
|
|
data.crisis_resolution_action = 'site_migrated'; |
6133
|
|
|
$( '#jp-id-crisis-question-1 .spinner' ).show(); |
6134
|
|
|
$.post( ajaxurl, data, function() { |
6135
|
|
|
$( '.jp-id-crisis-question' ).hide(); |
6136
|
|
|
$( '.banner-title' ).hide(); |
6137
|
|
|
$( '#jp-id-crisis-success' ).show(); |
6138
|
|
|
setTimeout( autodismissSuccessBanner, 6 * SECOND_IN_MS ); |
6139
|
|
|
}); |
6140
|
|
|
|
6141
|
|
|
}); |
6142
|
|
|
|
6143
|
|
|
// URL hasn't changed, next question please. |
6144
|
|
|
$( '.site-not-moved' ).click(function( e ) { |
6145
|
|
|
e.preventDefault(); |
6146
|
|
|
$( '.jp-id-crisis-question' ).hide(); |
6147
|
|
|
$( '#jp-id-crisis-question-2' ).show(); |
6148
|
|
|
}); |
6149
|
|
|
|
6150
|
|
|
// Reset connection: two separate sites. |
6151
|
|
|
$( '.reset-connection' ).click(function( e ) { |
6152
|
|
|
data.crisis_resolution_action = 'reset_connection'; |
6153
|
|
|
$.post( ajaxurl, data, function( response ) { |
6154
|
|
|
if ( 'reset-connection-success' === response ) { |
6155
|
|
|
window.location.replace( '<?php echo Jetpack::admin_url(); ?>' ); |
6156
|
|
|
} |
6157
|
|
|
}); |
6158
|
|
|
}); |
6159
|
|
|
|
6160
|
|
|
// It's a dev environment. Ignore. |
6161
|
|
|
$( '.is-dev-env' ).click(function( e ) { |
6162
|
|
|
data.crisis_resolution_action = 'whitelist'; |
6163
|
|
|
$( '#jp-id-crisis-question-2 .spinner' ).show(); |
6164
|
|
|
$.post( ajaxurl, data, function() { |
6165
|
|
|
$( '.jp-id-crisis-question' ).hide(); |
6166
|
|
|
$( '.banner-title' ).hide(); |
6167
|
|
|
$( '#jp-id-crisis-success' ).show(); |
6168
|
|
|
setTimeout( autodismissSuccessBanner, 4 * SECOND_IN_MS ); |
6169
|
|
|
}); |
6170
|
|
|
}); |
6171
|
|
|
|
6172
|
|
|
$( '.not-reconnecting' ).click(contactSupport); |
6173
|
|
|
$( '.not-staging-or-dev' ).click(contactSupport); |
6174
|
|
|
}); |
6175
|
|
|
})( jQuery ); |
6176
|
|
|
</script> |
6177
|
|
|
<?php |
6178
|
|
|
} |
6179
|
|
|
|
6180
|
|
|
/** |
6181
|
|
|
* Displays an admin_notice, alerting the user to an identity crisis. |
6182
|
|
|
*/ |
6183
|
|
|
public function alert_identity_crisis() { |
6184
|
|
|
// @todo temporary killing of feature in 3.8.1 as it revealed a number of scenarios not foreseen. |
|
|
|
|
6185
|
|
|
if ( ! Jetpack::is_development_version() ) { |
6186
|
|
|
return; |
6187
|
|
|
} |
6188
|
|
|
|
6189
|
|
|
// @todo temporary copout for dealing with domain mapping |
|
|
|
|
6190
|
|
|
// @see https://github.com/Automattic/jetpack/issues/2702 |
6191
|
|
|
if ( is_multisite() && defined( 'SUNRISE' ) && ! Jetpack::is_development_version() ) { |
6192
|
|
|
return; |
6193
|
|
|
} |
6194
|
|
|
|
6195
|
|
|
if ( ! current_user_can( 'jetpack_disconnect' ) ) { |
6196
|
|
|
return; |
6197
|
|
|
} |
6198
|
|
|
|
6199
|
|
|
if ( ! $errors = self::check_identity_crisis() ) { |
6200
|
|
|
return; |
6201
|
|
|
} |
6202
|
|
|
|
6203
|
|
|
// Only show on dashboard and jetpack pages |
6204
|
|
|
$screen = get_current_screen(); |
6205
|
|
|
if ( 'dashboard' !== $screen->base && ! did_action( 'jetpack_notices' ) ) { |
6206
|
|
|
return; |
6207
|
|
|
} |
6208
|
|
|
|
6209
|
|
|
// Include the js! |
6210
|
|
|
$ajax_nonce = wp_create_nonce( 'resolve-identity-crisis' ); |
6211
|
|
|
$this->identity_crisis_js( $ajax_nonce ); |
6212
|
|
|
|
6213
|
|
|
// Include the CSS! |
6214
|
|
|
if ( ! wp_script_is( 'jetpack', 'done' ) ) { |
6215
|
|
|
$this->admin_banner_styles(); |
6216
|
|
|
} |
6217
|
|
|
|
6218
|
|
|
if ( ! array_key_exists( 'error_code', $errors ) ) { |
6219
|
|
|
$key = 'siteurl'; |
6220
|
|
|
if ( ! $errors[ $key ] ) { |
6221
|
|
|
$key = 'home'; |
6222
|
|
|
} |
6223
|
|
|
} else { |
6224
|
|
|
$key = 'error_code'; |
6225
|
|
|
// 401 is the only error we care about. Any other errors should not trigger the alert. |
6226
|
|
|
if ( 401 !== $errors[ $key ] ) { |
6227
|
|
|
return; |
6228
|
|
|
} |
6229
|
|
|
} |
6230
|
|
|
|
6231
|
|
|
?> |
6232
|
|
|
|
6233
|
|
|
<style> |
6234
|
|
|
.jp-identity-crisis .jp-btn-group { |
6235
|
|
|
margin: 15px 0; |
6236
|
|
|
} |
6237
|
|
|
.jp-identity-crisis strong { |
6238
|
|
|
color: #518d2a; |
6239
|
|
|
} |
6240
|
|
|
.jp-identity-crisis.dismiss { |
6241
|
|
|
display: none; |
6242
|
|
|
} |
6243
|
|
|
.jp-identity-crisis .button { |
6244
|
|
|
margin-right: 4px; |
6245
|
|
|
} |
6246
|
|
|
</style> |
6247
|
|
|
|
6248
|
|
|
<div id="message" class="error jetpack-message jp-identity-crisis stay-visible"> |
6249
|
|
|
<div class="service-mark"></div> |
6250
|
|
|
<div class="jp-id-banner__content"> |
6251
|
|
|
<!-- <h3 class="banner-title"><?php _e( 'Something\'s not quite right with your Jetpack connection! Let\'s fix that.', 'jetpack' ); ?></h3> --> |
6252
|
|
|
|
6253
|
|
|
<div class="jp-id-crisis-question" id="jp-id-crisis-question-1"> |
6254
|
|
|
<?php |
6255
|
|
|
// 401 means that this site has been disconnected from wpcom, but the remote site still thinks it's connected. |
6256
|
|
|
if ( 'error_code' == $key && '401' == $errors[ $key ] ) : ?> |
6257
|
|
|
<div class="banner-content"> |
6258
|
|
|
<p><?php |
6259
|
|
|
/* translators: %s is a URL */ |
6260
|
|
|
printf( __( 'Our records show that this site does not have a valid connection to WordPress.com. Please reset your connection to fix this. <a href="%s" target="_blank">What caused this?</a>', 'jetpack' ), 'https://jetpack.me/support/no-valid-wordpress-com-connection/' ); |
6261
|
|
|
?></p> |
6262
|
|
|
</div> |
6263
|
|
|
<div class="jp-btn-group"> |
6264
|
|
|
<a href="#" class="reset-connection"><?php _e( 'Reset the connection', 'jetpack' ); ?></a> |
6265
|
|
|
<span class="idc-separator">|</span> |
6266
|
|
|
<a href="<?php echo esc_url( wp_nonce_url( Jetpack::admin_url( 'jetpack-notice=dismiss' ), 'jetpack-deactivate' ) ); ?>"><?php _e( 'Deactivate Jetpack', 'jetpack' ); ?></a> |
6267
|
|
|
</div> |
6268
|
|
|
<?php else : ?> |
6269
|
|
|
<div class="banner-content"> |
6270
|
|
|
<p><?php printf( __( 'It looks like you may have changed your domain. Is <strong>%1$s</strong> still your site\'s domain, or have you updated it to <strong> %2$s </strong>?', 'jetpack' ), $errors[ $key ], (string) get_option( $key ) ); ?></p> |
6271
|
|
|
</div> |
6272
|
|
|
<div class="jp-btn-group"> |
6273
|
|
|
<a href="#" class="regular site-moved"><?php printf( __( '%s is now my domain.', 'jetpack' ), $errors[ $key ] ); ?></a> <span class="idc-separator">|</span> <a href="#" class="site-not-moved" ><?php printf( __( '%s is still my domain.', 'jetpack' ), (string) get_option( $key ) ); ?></a> |
6274
|
|
|
<span class="spinner"></span> |
6275
|
|
|
</div> |
6276
|
|
|
<?php endif ; ?> |
6277
|
|
|
</div> |
6278
|
|
|
|
6279
|
|
|
<div class="jp-id-crisis-question" id="jp-id-crisis-question-2" style="display: none;"> |
6280
|
|
|
<div class="banner-content"> |
6281
|
|
|
<p><?php printf( |
6282
|
|
|
/* translators: %1$s, %2$s and %3$s are URLs */ |
6283
|
|
|
__( |
6284
|
|
|
'Are <strong> %2$s </strong> and <strong> %1$s </strong> two completely separate websites? If so we should create a new connection, which will reset your followers and linked services. <a href="%3$s"><em>What does this mean?</em></a>', |
6285
|
|
|
'jetpack' |
6286
|
|
|
), |
6287
|
|
|
$errors[ $key ], |
6288
|
|
|
(string) get_option( $key ), |
6289
|
|
|
'https://jetpack.me/support/what-does-resetting-the-connection-mean/' |
6290
|
|
|
); ?></p> |
6291
|
|
|
</div> |
6292
|
|
|
<div class="jp-btn-group"> |
6293
|
|
|
<a href="#" class="reset-connection"><?php _e( 'Reset the connection', 'jetpack' ); ?></a> <span class="idc-separator">|</span> |
6294
|
|
|
<a href="#" class="is-dev-env"><?php _e( 'This is a development environment', 'jetpack' ); ?></a> <span class="idc-separator">|</span> |
6295
|
|
|
<a href="https://jetpack.me/contact-support/" class="contact-support"><?php _e( 'Submit a support ticket', 'jetpack' ); ?></a> |
6296
|
|
|
<span class="spinner"></span> |
6297
|
|
|
</div> |
6298
|
|
|
</div> |
6299
|
|
|
|
6300
|
|
|
<div class="jp-id-crisis-success" id="jp-id-crisis-success" style="display: none;"> |
6301
|
|
|
<h3 class="success-notice"><?php printf( __( 'Thanks for taking the time to sort things out. We've updated our records accordingly!', 'jetpack' ) ); ?></h3> |
6302
|
|
|
</div> |
6303
|
|
|
</div> |
6304
|
|
|
</div> |
6305
|
|
|
|
6306
|
|
|
<?php |
6307
|
|
|
} |
6308
|
|
|
|
6309
|
|
|
/** |
6310
|
|
|
* Maybe Use a .min.css stylesheet, maybe not. |
6311
|
|
|
* |
6312
|
|
|
* Hooks onto `plugins_url` filter at priority 1, and accepts all 3 args. |
6313
|
|
|
*/ |
6314
|
|
|
public static function maybe_min_asset( $url, $path, $plugin ) { |
6315
|
|
|
// Short out on things trying to find actual paths. |
6316
|
|
|
if ( ! $path || empty( $plugin ) ) { |
6317
|
|
|
return $url; |
6318
|
|
|
} |
6319
|
|
|
|
6320
|
|
|
// Strip out the abspath. |
6321
|
|
|
$base = dirname( plugin_basename( $plugin ) ); |
6322
|
|
|
|
6323
|
|
|
// Short out on non-Jetpack assets. |
6324
|
|
|
if ( 'jetpack/' !== substr( $base, 0, 8 ) ) { |
6325
|
|
|
return $url; |
6326
|
|
|
} |
6327
|
|
|
|
6328
|
|
|
// File name parsing. |
6329
|
|
|
$file = "{$base}/{$path}"; |
6330
|
|
|
$full_path = JETPACK__PLUGIN_DIR . substr( $file, 8 ); |
6331
|
|
|
$file_name = substr( $full_path, strrpos( $full_path, '/' ) + 1 ); |
6332
|
|
|
$file_name_parts_r = array_reverse( explode( '.', $file_name ) ); |
6333
|
|
|
$extension = array_shift( $file_name_parts_r ); |
6334
|
|
|
|
6335
|
|
|
if ( in_array( strtolower( $extension ), array( 'css', 'js' ) ) ) { |
6336
|
|
|
// Already pointing at the minified version. |
6337
|
|
|
if ( 'min' === $file_name_parts_r[0] ) { |
6338
|
|
|
return $url; |
6339
|
|
|
} |
6340
|
|
|
|
6341
|
|
|
$min_full_path = preg_replace( "#\.{$extension}$#", ".min.{$extension}", $full_path ); |
6342
|
|
|
if ( file_exists( $min_full_path ) ) { |
6343
|
|
|
$url = preg_replace( "#\.{$extension}$#", ".min.{$extension}", $url ); |
6344
|
|
|
} |
6345
|
|
|
} |
6346
|
|
|
|
6347
|
|
|
return $url; |
6348
|
|
|
} |
6349
|
|
|
|
6350
|
|
|
/** |
6351
|
|
|
* Maybe inlines a stylesheet. |
6352
|
|
|
* |
6353
|
|
|
* If you'd like to inline a stylesheet instead of printing a link to it, |
6354
|
|
|
* wp_style_add_data( 'handle', 'jetpack-inline', true ); |
6355
|
|
|
* |
6356
|
|
|
* Attached to `style_loader_tag` filter. |
6357
|
|
|
* |
6358
|
|
|
* @param string $tag The tag that would link to the external asset. |
6359
|
|
|
* @param string $handle The registered handle of the script in question. |
6360
|
|
|
* |
6361
|
|
|
* @return string |
6362
|
|
|
*/ |
6363
|
|
|
public static function maybe_inline_style( $tag, $handle ) { |
6364
|
|
|
global $wp_styles; |
6365
|
|
|
$item = $wp_styles->registered[ $handle ]; |
6366
|
|
|
|
6367
|
|
|
if ( ! isset( $item->extra['jetpack-inline'] ) || ! $item->extra['jetpack-inline'] ) { |
6368
|
|
|
return $tag; |
6369
|
|
|
} |
6370
|
|
|
|
6371
|
|
|
if ( preg_match( '# href=\'([^\']+)\' #i', $tag, $matches ) ) { |
6372
|
|
|
$href = $matches[1]; |
6373
|
|
|
// Strip off query string |
6374
|
|
|
if ( $pos = strpos( $href, '?' ) ) { |
6375
|
|
|
$href = substr( $href, 0, $pos ); |
6376
|
|
|
} |
6377
|
|
|
// Strip off fragment |
6378
|
|
|
if ( $pos = strpos( $href, '#' ) ) { |
6379
|
|
|
$href = substr( $href, 0, $pos ); |
6380
|
|
|
} |
6381
|
|
|
} else { |
6382
|
|
|
return $tag; |
6383
|
|
|
} |
6384
|
|
|
|
6385
|
|
|
$plugins_dir = plugin_dir_url( JETPACK__PLUGIN_FILE ); |
6386
|
|
|
if ( $plugins_dir !== substr( $href, 0, strlen( $plugins_dir ) ) ) { |
6387
|
|
|
return $tag; |
6388
|
|
|
} |
6389
|
|
|
|
6390
|
|
|
// If this stylesheet has a RTL version, and the RTL version replaces normal... |
6391
|
|
|
if ( isset( $item->extra['rtl'] ) && 'replace' === $item->extra['rtl'] && is_rtl() ) { |
6392
|
|
|
// And this isn't the pass that actually deals with the RTL version... |
6393
|
|
|
if ( false === strpos( $tag, " id='$handle-rtl-css' " ) ) { |
6394
|
|
|
// Short out, as the RTL version will deal with it in a moment. |
6395
|
|
|
return $tag; |
6396
|
|
|
} |
6397
|
|
|
} |
6398
|
|
|
|
6399
|
|
|
$file = JETPACK__PLUGIN_DIR . substr( $href, strlen( $plugins_dir ) ); |
6400
|
|
|
$css = Jetpack::absolutize_css_urls( file_get_contents( $file ), $href ); |
6401
|
|
|
if ( $css ) { |
6402
|
|
|
$tag = "<!-- Inline {$item->handle} -->\r\n"; |
6403
|
|
|
if ( empty( $item->extra['after'] ) ) { |
6404
|
|
|
wp_add_inline_style( $handle, $css ); |
6405
|
|
|
} else { |
6406
|
|
|
array_unshift( $item->extra['after'], $css ); |
6407
|
|
|
wp_style_add_data( $handle, 'after', $item->extra['after'] ); |
6408
|
|
|
} |
6409
|
|
|
} |
6410
|
|
|
|
6411
|
|
|
return $tag; |
6412
|
|
|
} |
6413
|
|
|
|
6414
|
|
|
/** |
6415
|
|
|
* Loads a view file from the views |
6416
|
|
|
* |
6417
|
|
|
* Data passed in with the $data parameter will be available in the |
6418
|
|
|
* template file as $data['value'] |
6419
|
|
|
* |
6420
|
|
|
* @param string $template - Template file to load |
6421
|
|
|
* @param array $data - Any data to pass along to the template |
6422
|
|
|
* @return boolean - If template file was found |
6423
|
|
|
**/ |
6424
|
|
|
public function load_view( $template, $data = array() ) { |
6425
|
|
|
$views_dir = JETPACK__PLUGIN_DIR . 'views/'; |
6426
|
|
|
|
6427
|
|
|
if( file_exists( $views_dir . $template ) ) { |
6428
|
|
|
require_once( $views_dir . $template ); |
6429
|
|
|
return true; |
6430
|
|
|
} |
6431
|
|
|
|
6432
|
|
|
error_log( "Jetpack: Unable to find view file $views_dir$template" ); |
6433
|
|
|
return false; |
6434
|
|
|
} |
6435
|
|
|
|
6436
|
|
|
/** |
6437
|
|
|
* Sends a ping to the Jetpack servers to toggle on/off remote portions |
6438
|
|
|
* required by some modules. |
6439
|
|
|
* |
6440
|
|
|
* @param string $module_slug |
6441
|
|
|
*/ |
6442
|
|
|
public function toggle_module_on_wpcom( $module_slug ) { |
6443
|
|
|
Jetpack::init()->sync->register( 'noop' ); |
6444
|
|
|
|
6445
|
|
|
if ( false !== strpos( current_filter(), 'jetpack_activate_module_' ) ) { |
6446
|
|
|
self::check_privacy( $module_slug ); |
6447
|
|
|
} |
6448
|
|
|
|
6449
|
|
|
} |
6450
|
|
|
|
6451
|
|
|
/** |
6452
|
|
|
* Throws warnings for deprecated hooks to be removed from Jetpack |
6453
|
|
|
*/ |
6454
|
|
|
public function deprecated_hooks() { |
6455
|
|
|
global $wp_filter; |
6456
|
|
|
|
6457
|
|
|
/* |
6458
|
|
|
* Format: |
6459
|
|
|
* deprecated_filter_name => replacement_name |
6460
|
|
|
* |
6461
|
|
|
* If there is no replacement us null for replacement_name |
6462
|
|
|
*/ |
6463
|
|
|
$deprecated_list = array( |
6464
|
|
|
'jetpack_bail_on_shortcode' => 'jetpack_shortcodes_to_include', |
6465
|
|
|
'wpl_sharing_2014_1' => null, |
6466
|
|
|
'jetpack-tools-to-include' => 'jetpack_tools_to_include', |
6467
|
|
|
); |
6468
|
|
|
|
6469
|
|
|
// This is a silly loop depth. Better way? |
6470
|
|
|
foreach( $deprecated_list AS $hook => $hook_alt ) { |
6471
|
|
|
if( isset( $wp_filter[ $hook ] ) && is_array( $wp_filter[ $hook ] ) ) { |
6472
|
|
|
foreach( $wp_filter[$hook] AS $func => $values ) { |
6473
|
|
|
foreach( $values AS $hooked ) { |
6474
|
|
|
_deprecated_function( $hook . ' used for ' . $hooked['function'], null, $hook_alt ); |
6475
|
|
|
} |
6476
|
|
|
} |
6477
|
|
|
} |
6478
|
|
|
} |
6479
|
|
|
} |
6480
|
|
|
|
6481
|
|
|
/** |
6482
|
|
|
* Converts any url in a stylesheet, to the correct absolute url. |
6483
|
|
|
* |
6484
|
|
|
* Considerations: |
6485
|
|
|
* - Normal, relative URLs `feh.png` |
6486
|
|
|
* - Data URLs `data:image/gif;base64,eh129ehiuehjdhsa==` |
6487
|
|
|
* - Schema-agnostic URLs `//domain.com/feh.png` |
6488
|
|
|
* - Absolute URLs `http://domain.com/feh.png` |
6489
|
|
|
* - Domain root relative URLs `/feh.png` |
6490
|
|
|
* |
6491
|
|
|
* @param $css string: The raw CSS -- should be read in directly from the file. |
6492
|
|
|
* @param $css_file_url : The URL that the file can be accessed at, for calculating paths from. |
6493
|
|
|
* |
6494
|
|
|
* @return mixed|string |
6495
|
|
|
*/ |
6496
|
|
|
public static function absolutize_css_urls( $css, $css_file_url ) { |
6497
|
|
|
$pattern = '#url\((?P<path>[^)]*)\)#i'; |
6498
|
|
|
$css_dir = dirname( $css_file_url ); |
6499
|
|
|
$p = parse_url( $css_dir ); |
6500
|
|
|
$domain = sprintf( |
6501
|
|
|
'%1$s//%2$s%3$s%4$s', |
6502
|
|
|
isset( $p['scheme'] ) ? "{$p['scheme']}:" : '', |
6503
|
|
|
isset( $p['user'], $p['pass'] ) ? "{$p['user']}:{$p['pass']}@" : '', |
6504
|
|
|
$p['host'], |
6505
|
|
|
isset( $p['port'] ) ? ":{$p['port']}" : '' |
6506
|
|
|
); |
6507
|
|
|
|
6508
|
|
|
if ( preg_match_all( $pattern, $css, $matches, PREG_SET_ORDER ) ) { |
6509
|
|
|
$find = $replace = array(); |
6510
|
|
|
foreach ( $matches as $match ) { |
6511
|
|
|
$url = trim( $match['path'], "'\" \t" ); |
6512
|
|
|
|
6513
|
|
|
// If this is a data url, we don't want to mess with it. |
6514
|
|
|
if ( 'data:' === substr( $url, 0, 5 ) ) { |
6515
|
|
|
continue; |
6516
|
|
|
} |
6517
|
|
|
|
6518
|
|
|
// If this is an absolute or protocol-agnostic url, |
6519
|
|
|
// we don't want to mess with it. |
6520
|
|
|
if ( preg_match( '#^(https?:)?//#i', $url ) ) { |
6521
|
|
|
continue; |
6522
|
|
|
} |
6523
|
|
|
|
6524
|
|
|
switch ( substr( $url, 0, 1 ) ) { |
6525
|
|
|
case '/': |
6526
|
|
|
$absolute = $domain . $url; |
6527
|
|
|
break; |
6528
|
|
|
default: |
6529
|
|
|
$absolute = $css_dir . '/' . $url; |
6530
|
|
|
} |
6531
|
|
|
|
6532
|
|
|
$find[] = $match[0]; |
6533
|
|
|
$replace[] = sprintf( 'url("%s")', $absolute ); |
6534
|
|
|
} |
6535
|
|
|
$css = str_replace( $find, $replace, $css ); |
6536
|
|
|
} |
6537
|
|
|
|
6538
|
|
|
return $css; |
6539
|
|
|
} |
6540
|
|
|
|
6541
|
|
|
/** |
6542
|
|
|
* This method checks to see if SSL is required by the site in |
6543
|
|
|
* order to visit it in some way other than only setting the |
6544
|
|
|
* https value in the home or siteurl values. |
6545
|
|
|
* |
6546
|
|
|
* @since 3.2 |
6547
|
|
|
* @return boolean |
6548
|
|
|
**/ |
6549
|
|
|
private function is_ssl_required_to_visit_site() { |
6550
|
|
|
global $wp_version; |
6551
|
|
|
$ssl = is_ssl(); |
6552
|
|
|
|
6553
|
|
|
if ( force_ssl_admin() ) { |
6554
|
|
|
$ssl = true; |
6555
|
|
|
} |
6556
|
|
|
return $ssl; |
6557
|
|
|
} |
6558
|
|
|
|
6559
|
|
|
/** |
6560
|
|
|
* This methods removes all of the registered css files on the frontend |
6561
|
|
|
* from Jetpack in favor of using a single file. In effect "imploding" |
6562
|
|
|
* all the files into one file. |
6563
|
|
|
* |
6564
|
|
|
* Pros: |
6565
|
|
|
* - Uses only ONE css asset connection instead of 15 |
6566
|
|
|
* - Saves a minimum of 56k |
6567
|
|
|
* - Reduces server load |
6568
|
|
|
* - Reduces time to first painted byte |
6569
|
|
|
* |
6570
|
|
|
* Cons: |
6571
|
|
|
* - Loads css for ALL modules. However all selectors are prefixed so it |
6572
|
|
|
* should not cause any issues with themes. |
6573
|
|
|
* - Plugins/themes dequeuing styles no longer do anything. See |
6574
|
|
|
* jetpack_implode_frontend_css filter for a workaround |
6575
|
|
|
* |
6576
|
|
|
* For some situations developers may wish to disable css imploding and |
6577
|
|
|
* instead operate in legacy mode where each file loads seperately and |
6578
|
|
|
* can be edited individually or dequeued. This can be accomplished with |
6579
|
|
|
* the following line: |
6580
|
|
|
* |
6581
|
|
|
* add_filter( 'jetpack_implode_frontend_css', '__return_false' ); |
6582
|
|
|
* |
6583
|
|
|
* @since 3.2 |
6584
|
|
|
**/ |
6585
|
|
|
public function implode_frontend_css( $travis_test = false ) { |
6586
|
|
|
$do_implode = true; |
6587
|
|
|
if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) { |
6588
|
|
|
$do_implode = false; |
6589
|
|
|
} |
6590
|
|
|
|
6591
|
|
|
/** |
6592
|
|
|
* Allow CSS to be concatenated into a single jetpack.css file. |
6593
|
|
|
* |
6594
|
|
|
* @since 3.2.0 |
6595
|
|
|
* |
6596
|
|
|
* @param bool $do_implode Should CSS be concatenated? Default to true. |
6597
|
|
|
*/ |
6598
|
|
|
$do_implode = apply_filters( 'jetpack_implode_frontend_css', $do_implode ); |
6599
|
|
|
|
6600
|
|
|
// Do not use the imploded file when default behaviour was altered through the filter |
6601
|
|
|
if ( ! $do_implode ) { |
6602
|
|
|
return; |
6603
|
|
|
} |
6604
|
|
|
|
6605
|
|
|
// We do not want to use the imploded file in dev mode, or if not connected |
6606
|
|
|
if ( Jetpack::is_development_mode() || ! self::is_active() ) { |
6607
|
|
|
if ( ! $travis_test ) { |
6608
|
|
|
return; |
6609
|
|
|
} |
6610
|
|
|
} |
6611
|
|
|
|
6612
|
|
|
// Do not use the imploded file if sharing css was dequeued via the sharing settings screen |
6613
|
|
|
if ( get_option( 'sharedaddy_disable_resources' ) ) { |
6614
|
|
|
return; |
6615
|
|
|
} |
6616
|
|
|
|
6617
|
|
|
/* |
6618
|
|
|
* Now we assume Jetpack is connected and able to serve the single |
6619
|
|
|
* file. |
6620
|
|
|
* |
6621
|
|
|
* In the future there will be a check here to serve the file locally |
6622
|
|
|
* or potentially from the Jetpack CDN |
6623
|
|
|
* |
6624
|
|
|
* For now: |
6625
|
|
|
* - Enqueue a single imploded css file |
6626
|
|
|
* - Zero out the style_loader_tag for the bundled ones |
6627
|
|
|
* - Be happy, drink scotch |
6628
|
|
|
*/ |
6629
|
|
|
|
6630
|
|
|
add_filter( 'style_loader_tag', array( $this, 'concat_remove_style_loader_tag' ), 10, 2 ); |
6631
|
|
|
|
6632
|
|
|
$version = Jetpack::is_development_version() ? filemtime( JETPACK__PLUGIN_DIR . 'css/jetpack.css' ) : JETPACK__VERSION; |
6633
|
|
|
|
6634
|
|
|
wp_enqueue_style( 'jetpack_css', plugins_url( 'css/jetpack.css', __FILE__ ), array(), $version ); |
6635
|
|
|
wp_style_add_data( 'jetpack_css', 'rtl', 'replace' ); |
6636
|
|
|
} |
6637
|
|
|
|
6638
|
|
|
function concat_remove_style_loader_tag( $tag, $handle ) { |
6639
|
|
|
if ( in_array( $handle, $this->concatenated_style_handles ) ) { |
6640
|
|
|
$tag = ''; |
6641
|
|
|
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) { |
6642
|
|
|
$tag = "<!-- `" . esc_html( $handle ) . "` is included in the concatenated jetpack.css -->\r\n"; |
6643
|
|
|
} |
6644
|
|
|
} |
6645
|
|
|
|
6646
|
|
|
return $tag; |
6647
|
|
|
} |
6648
|
|
|
|
6649
|
|
|
/* |
6650
|
|
|
* Check the heartbeat data |
6651
|
|
|
* |
6652
|
|
|
* Organizes the heartbeat data by severity. For example, if the site |
6653
|
|
|
* is in an ID crisis, it will be in the $filtered_data['bad'] array. |
6654
|
|
|
* |
6655
|
|
|
* Data will be added to "caution" array, if it either: |
6656
|
|
|
* - Out of date Jetpack version |
6657
|
|
|
* - Out of date WP version |
6658
|
|
|
* - Out of date PHP version |
6659
|
|
|
* |
6660
|
|
|
* $return array $filtered_data |
6661
|
|
|
*/ |
6662
|
|
|
public static function jetpack_check_heartbeat_data() { |
6663
|
|
|
$raw_data = Jetpack_Heartbeat::generate_stats_array(); |
6664
|
|
|
|
6665
|
|
|
$good = array(); |
6666
|
|
|
$caution = array(); |
6667
|
|
|
$bad = array(); |
6668
|
|
|
|
6669
|
|
|
foreach ( $raw_data as $stat => $value ) { |
6670
|
|
|
|
6671
|
|
|
// Check jetpack version |
6672
|
|
|
if ( 'version' == $stat ) { |
6673
|
|
|
if ( version_compare( $value, JETPACK__VERSION, '<' ) ) { |
6674
|
|
|
$caution[ $stat ] = $value . " - min supported is " . JETPACK__VERSION; |
6675
|
|
|
continue; |
6676
|
|
|
} |
6677
|
|
|
} |
6678
|
|
|
|
6679
|
|
|
// Check WP version |
6680
|
|
|
if ( 'wp-version' == $stat ) { |
6681
|
|
|
if ( version_compare( $value, JETPACK__MINIMUM_WP_VERSION, '<' ) ) { |
6682
|
|
|
$caution[ $stat ] = $value . " - min supported is " . JETPACK__MINIMUM_WP_VERSION; |
6683
|
|
|
continue; |
6684
|
|
|
} |
6685
|
|
|
} |
6686
|
|
|
|
6687
|
|
|
// Check PHP version |
6688
|
|
|
if ( 'php-version' == $stat ) { |
6689
|
|
|
if ( version_compare( PHP_VERSION, '5.2.4', '<' ) ) { |
6690
|
|
|
$caution[ $stat ] = $value . " - min supported is 5.2.4"; |
6691
|
|
|
continue; |
6692
|
|
|
} |
6693
|
|
|
} |
6694
|
|
|
|
6695
|
|
|
// Check ID crisis |
6696
|
|
|
if ( 'identitycrisis' == $stat ) { |
6697
|
|
|
if ( 'yes' == $value ) { |
6698
|
|
|
$bad[ $stat ] = $value; |
6699
|
|
|
continue; |
6700
|
|
|
} |
6701
|
|
|
} |
6702
|
|
|
|
6703
|
|
|
// The rest are good :) |
6704
|
|
|
$good[ $stat ] = $value; |
6705
|
|
|
} |
6706
|
|
|
|
6707
|
|
|
$filtered_data = array( |
6708
|
|
|
'good' => $good, |
6709
|
|
|
'caution' => $caution, |
6710
|
|
|
'bad' => $bad |
6711
|
|
|
); |
6712
|
|
|
|
6713
|
|
|
return $filtered_data; |
6714
|
|
|
} |
6715
|
|
|
|
6716
|
|
|
|
6717
|
|
|
/* |
6718
|
|
|
* This method is used to organize all options that can be reset |
6719
|
|
|
* without disconnecting Jetpack. |
6720
|
|
|
* |
6721
|
|
|
* It is used in class.jetpack-cli.php to reset options |
6722
|
|
|
* |
6723
|
|
|
* @return array of options to delete. |
6724
|
|
|
*/ |
6725
|
|
|
public static function get_jetpack_options_for_reset() { |
6726
|
|
|
$jetpack_options = Jetpack_Options::get_option_names(); |
6727
|
|
|
$jetpack_options_non_compat = Jetpack_Options::get_option_names( 'non_compact' ); |
6728
|
|
|
$jetpack_options_private = Jetpack_Options::get_option_names( 'private' ); |
6729
|
|
|
|
6730
|
|
|
$all_jp_options = array_merge( $jetpack_options, $jetpack_options_non_compat, $jetpack_options_private ); |
6731
|
|
|
|
6732
|
|
|
// A manual build of the wp options |
6733
|
|
|
$wp_options = array( |
6734
|
|
|
'sharing-options', |
6735
|
|
|
'disabled_likes', |
6736
|
|
|
'disabled_reblogs', |
6737
|
|
|
'jetpack_comments_likes_enabled', |
6738
|
|
|
'wp_mobile_excerpt', |
6739
|
|
|
'wp_mobile_featured_images', |
6740
|
|
|
'wp_mobile_app_promos', |
6741
|
|
|
'stats_options', |
6742
|
|
|
'stats_dashboard_widget', |
6743
|
|
|
'safecss_preview_rev', |
6744
|
|
|
'safecss_rev', |
6745
|
|
|
'safecss_revision_migrated', |
6746
|
|
|
'nova_menu_order', |
6747
|
|
|
'jetpack_portfolio', |
6748
|
|
|
'jetpack_portfolio_posts_per_page', |
6749
|
|
|
'jetpack_testimonial', |
6750
|
|
|
'jetpack_testimonial_posts_per_page', |
6751
|
|
|
'wp_mobile_custom_css', |
6752
|
|
|
'sharedaddy_disable_resources', |
6753
|
|
|
'sharing-options', |
6754
|
|
|
'sharing-services', |
6755
|
|
|
'site_icon_temp_data', |
6756
|
|
|
'featured-content', |
6757
|
|
|
'site_logo', |
6758
|
|
|
); |
6759
|
|
|
|
6760
|
|
|
// Flag some Jetpack options as unsafe |
6761
|
|
|
$unsafe_options = array( |
6762
|
|
|
'id', // (int) The Client ID/WP.com Blog ID of this site. |
6763
|
|
|
'master_user', // (int) The local User ID of the user who connected this site to jetpack.wordpress.com. |
6764
|
|
|
'version', // (string) Used during upgrade procedure to auto-activate new modules. version:time |
6765
|
|
|
'jumpstart', // (string) A flag for whether or not to show the Jump Start. Accepts: new_connection, jumpstart_activated, jetpack_action_taken, jumpstart_dismissed. |
6766
|
|
|
|
6767
|
|
|
// non_compact |
6768
|
|
|
'activated', |
6769
|
|
|
|
6770
|
|
|
// private |
6771
|
|
|
'register', |
6772
|
|
|
'blog_token', // (string) The Client Secret/Blog Token of this site. |
6773
|
|
|
'user_token', // (string) The User Token of this site. (deprecated) |
6774
|
|
|
'user_tokens' |
6775
|
|
|
); |
6776
|
|
|
|
6777
|
|
|
// Remove the unsafe Jetpack options |
6778
|
|
|
foreach ( $unsafe_options as $unsafe_option ) { |
6779
|
|
|
if ( false !== ( $key = array_search( $unsafe_option, $all_jp_options ) ) ) { |
6780
|
|
|
unset( $all_jp_options[ $key ] ); |
6781
|
|
|
} |
6782
|
|
|
} |
6783
|
|
|
|
6784
|
|
|
$options = array( |
6785
|
|
|
'jp_options' => $all_jp_options, |
6786
|
|
|
'wp_options' => $wp_options |
6787
|
|
|
); |
6788
|
|
|
|
6789
|
|
|
return $options; |
6790
|
|
|
} |
6791
|
|
|
|
6792
|
|
|
/* |
6793
|
|
|
* Check if an option of a Jetpack module has been updated. |
6794
|
|
|
* |
6795
|
|
|
* If any module option has been updated before Jump Start has been dismissed, |
6796
|
|
|
* update the 'jumpstart' option so we can hide Jump Start. |
6797
|
|
|
*/ |
6798
|
|
|
public static function jumpstart_has_updated_module_option( $option_name = '' ) { |
6799
|
|
|
// Bail if Jump Start has already been dismissed |
6800
|
|
|
if ( 'new_connection' !== Jetpack::get_option( 'jumpstart' ) ) { |
6801
|
|
|
return false; |
6802
|
|
|
} |
6803
|
|
|
|
6804
|
|
|
$jetpack = Jetpack::init(); |
6805
|
|
|
|
6806
|
|
|
|
6807
|
|
|
// Manual build of module options |
6808
|
|
|
$option_names = self::get_jetpack_options_for_reset(); |
6809
|
|
|
|
6810
|
|
|
if ( in_array( $option_name, $option_names['wp_options'] ) ) { |
6811
|
|
|
Jetpack_Options::update_option( 'jumpstart', 'jetpack_action_taken' ); |
6812
|
|
|
|
6813
|
|
|
//Jump start is being dismissed send data to MC Stats |
6814
|
|
|
$jetpack->stat( 'jumpstart', 'manual,'.$option_name ); |
6815
|
|
|
|
6816
|
|
|
$jetpack->do_stats( 'server_side' ); |
6817
|
|
|
} |
6818
|
|
|
|
6819
|
|
|
} |
6820
|
|
|
|
6821
|
|
|
/* |
6822
|
|
|
* Strip http:// or https:// from a url, replaces forward slash with ::, |
6823
|
|
|
* so we can bring them directly to their site in calypso. |
6824
|
|
|
* |
6825
|
|
|
* @param string | url |
6826
|
|
|
* @return string | url without the guff |
6827
|
|
|
*/ |
6828
|
|
|
public static function build_raw_urls( $url ) { |
6829
|
|
|
$strip_http = '/.*?:\/\//i'; |
6830
|
|
|
$url = preg_replace( $strip_http, '', $url ); |
6831
|
|
|
$url = str_replace( '/', '::', $url ); |
6832
|
|
|
return $url; |
6833
|
|
|
} |
6834
|
|
|
|
6835
|
|
|
/** |
6836
|
|
|
* Stores and prints out domains to prefetch for page speed optimization. |
6837
|
|
|
* |
6838
|
|
|
* @param mixed $new_urls |
6839
|
|
|
*/ |
6840
|
|
|
public static function dns_prefetch( $new_urls = null ) { |
6841
|
|
|
static $prefetch_urls = array(); |
6842
|
|
|
if ( empty( $new_urls ) && ! empty( $prefetch_urls ) ) { |
6843
|
|
|
echo "\r\n"; |
6844
|
|
|
foreach ( $prefetch_urls as $this_prefetch_url ) { |
6845
|
|
|
printf( "<link rel='dns-prefetch' href='%s'>\r\n", esc_attr( $this_prefetch_url ) ); |
6846
|
|
|
} |
6847
|
|
|
} elseif ( ! empty( $new_urls ) ) { |
6848
|
|
|
if ( ! has_action( 'wp_head', array( __CLASS__, __FUNCTION__ ) ) ) { |
6849
|
|
|
add_action( 'wp_head', array( __CLASS__, __FUNCTION__ ) ); |
6850
|
|
|
} |
6851
|
|
|
foreach ( (array) $new_urls as $this_new_url ) { |
6852
|
|
|
$prefetch_urls[] = strtolower( untrailingslashit( preg_replace( '#^https?://#i', '//', $this_new_url ) ) ); |
6853
|
|
|
} |
6854
|
|
|
$prefetch_urls = array_unique( $prefetch_urls ); |
6855
|
|
|
} |
6856
|
|
|
} |
6857
|
|
|
|
6858
|
|
|
public function wp_dashboard_setup() { |
6859
|
|
|
if ( self::is_active() ) { |
6860
|
|
|
add_action( 'jetpack_dashboard_widget', array( __CLASS__, 'dashboard_widget_footer' ), 999 ); |
6861
|
|
|
$widget_title = __( 'Site Stats', 'jetpack' ); |
6862
|
|
|
} elseif ( ! self::is_development_mode() && current_user_can( 'jetpack_connect' ) ) { |
6863
|
|
|
add_action( 'jetpack_dashboard_widget', array( $this, 'dashboard_widget_connect_to_wpcom' ) ); |
6864
|
|
|
$widget_title = __( 'Please Connect Jetpack', 'jetpack' ); |
6865
|
|
|
} |
6866
|
|
|
|
6867
|
|
|
if ( has_action( 'jetpack_dashboard_widget' ) ) { |
6868
|
|
|
wp_add_dashboard_widget( |
6869
|
|
|
'jetpack_summary_widget', |
6870
|
|
|
$widget_title, |
|
|
|
|
6871
|
|
|
array( __CLASS__, 'dashboard_widget' ) |
6872
|
|
|
); |
6873
|
|
|
wp_enqueue_style( 'jetpack-dashboard-widget', plugins_url( 'css/dashboard-widget.css', JETPACK__PLUGIN_FILE ), array(), JETPACK__VERSION ); |
6874
|
|
|
|
6875
|
|
|
// If we're inactive and not in development mode, sort our box to the top. |
6876
|
|
|
if ( ! self::is_active() && ! self::is_development_mode() ) { |
6877
|
|
|
global $wp_meta_boxes; |
6878
|
|
|
|
6879
|
|
|
$dashboard = $wp_meta_boxes['dashboard']['normal']['core']; |
6880
|
|
|
$ours = array( 'jetpack_summary_widget' => $dashboard['jetpack_summary_widget'] ); |
6881
|
|
|
|
6882
|
|
|
$wp_meta_boxes['dashboard']['normal']['core'] = array_merge( $ours, $dashboard ); |
6883
|
|
|
} |
6884
|
|
|
} |
6885
|
|
|
} |
6886
|
|
|
|
6887
|
|
|
/** |
6888
|
|
|
* @param mixed $result Value for the user's option |
|
|
|
|
6889
|
|
|
* @return mixed |
6890
|
|
|
*/ |
6891
|
|
|
function get_user_option_meta_box_order_dashboard( $sorted ) { |
6892
|
|
|
if ( ! is_array( $sorted ) ) { |
6893
|
|
|
return $sorted; |
6894
|
|
|
} |
6895
|
|
|
|
6896
|
|
|
foreach ( $sorted as $box_context => $ids ) { |
6897
|
|
|
if ( false === strpos( $ids, 'dashboard_stats' ) ) { |
6898
|
|
|
// If the old id isn't anywhere in the ids, don't bother exploding and fail out. |
6899
|
|
|
continue; |
6900
|
|
|
} |
6901
|
|
|
|
6902
|
|
|
$ids_array = explode( ',', $ids ); |
6903
|
|
|
$key = array_search( 'dashboard_stats', $ids_array ); |
6904
|
|
|
|
6905
|
|
|
if ( false !== $key ) { |
6906
|
|
|
// If we've found that exact value in the option (and not `google_dashboard_stats` for example) |
6907
|
|
|
$ids_array[ $key ] = 'jetpack_summary_widget'; |
6908
|
|
|
$sorted[ $box_context ] = implode( ',', $ids_array ); |
6909
|
|
|
// We've found it, stop searching, and just return. |
6910
|
|
|
break; |
6911
|
|
|
} |
6912
|
|
|
} |
6913
|
|
|
|
6914
|
|
|
return $sorted; |
6915
|
|
|
} |
6916
|
|
|
|
6917
|
|
|
public static function dashboard_widget() { |
6918
|
|
|
/** |
6919
|
|
|
* Fires when the dashboard is loaded. |
6920
|
|
|
* |
6921
|
|
|
* @since 3.4.0 |
6922
|
|
|
*/ |
6923
|
|
|
do_action( 'jetpack_dashboard_widget' ); |
6924
|
|
|
} |
6925
|
|
|
|
6926
|
|
|
public static function dashboard_widget_footer() { |
6927
|
|
|
?> |
6928
|
|
|
<footer> |
6929
|
|
|
|
6930
|
|
|
<div class="protect"> |
6931
|
|
|
<?php if ( Jetpack::is_module_active( 'protect' ) ) : ?> |
6932
|
|
|
<h3><?php echo number_format_i18n( get_site_option( 'jetpack_protect_blocked_attempts', 0 ) ); ?></h3> |
6933
|
|
|
<p><?php echo esc_html_x( 'Blocked malicious login attempts', '{#} Blocked malicious login attempts -- number is on a prior line, text is a caption.', 'jetpack' ); ?></p> |
6934
|
|
|
<?php elseif ( current_user_can( 'jetpack_activate_modules' ) && ! self::is_development_mode() ) : ?> |
6935
|
|
|
<a href="<?php echo esc_url( wp_nonce_url( Jetpack::admin_url( array( 'action' => 'activate', 'module' => 'protect' ) ), 'jetpack_activate-protect' ) ); ?>" class="button button-jetpack" title="<?php esc_attr_e( 'Protect helps to keep you secure from brute-force login attacks.', 'jetpack' ); ?>"> |
6936
|
|
|
<?php esc_html_e( 'Activate Protect', 'jetpack' ); ?> |
6937
|
|
|
</a> |
6938
|
|
|
<?php else : ?> |
6939
|
|
|
<?php esc_html_e( 'Protect is inactive.', 'jetpack' ); ?> |
6940
|
|
|
<?php endif; ?> |
6941
|
|
|
</div> |
6942
|
|
|
|
6943
|
|
|
<div class="akismet"> |
6944
|
|
|
<?php if ( is_plugin_active( 'akismet/akismet.php' ) ) : ?> |
6945
|
|
|
<h3><?php echo number_format_i18n( get_option( 'akismet_spam_count', 0 ) ); ?></h3> |
6946
|
|
|
<p><?php echo esc_html_x( 'Spam comments blocked by Akismet.', '{#} Spam comments blocked by Akismet -- number is on a prior line, text is a caption.', 'jetpack' ); ?></p> |
6947
|
|
View Code Duplication |
<?php elseif ( current_user_can( 'activate_plugins' ) && ! is_wp_error( validate_plugin( 'akismet/akismet.php' ) ) ) : ?> |
6948
|
|
|
<a href="<?php echo esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'activate', 'plugin' => 'akismet/akismet.php' ), admin_url( 'plugins.php' ) ), 'activate-plugin_akismet/akismet.php' ) ); ?>" class="button button-jetpack"> |
6949
|
|
|
<?php esc_html_e( 'Activate Akismet', 'jetpack' ); ?> |
6950
|
|
|
</a> |
6951
|
|
|
<?php else : ?> |
6952
|
|
|
<p><a href="<?php echo esc_url( 'https://akismet.com/?utm_source=jetpack&utm_medium=link&utm_campaign=Jetpack%20Dashboard%20Widget%20Footer%20Link' ); ?>"><?php esc_html_e( 'Akismet can help to keep your blog safe from spam!', 'jetpack' ); ?></a></p> |
6953
|
|
|
<?php endif; ?> |
6954
|
|
|
</div> |
6955
|
|
|
|
6956
|
|
|
|
6957
|
|
View Code Duplication |
<?php if ( ! current_user_can( 'edit_posts' ) && self::is_user_connected() ) : ?> |
6958
|
|
|
<div style="width: 100%; text-align: center; padding-top: 20px; clear: both;"><a class="button" title="<?php esc_attr_e( 'Unlink your account from WordPress.com', 'jetpack' ); ?>" href="<?php echo esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'unlink', 'redirect' => 'sub-unlink' ), admin_url( 'index.php' ) ), 'jetpack-unlink' ) ); ?>"><?php esc_html_e( 'Unlink your account from WordPress.com', 'jetpack' ); ?></a></div> |
6959
|
|
|
<?php endif; ?> |
6960
|
|
|
|
6961
|
|
|
</footer> |
6962
|
|
|
<?php |
6963
|
|
|
} |
6964
|
|
|
|
6965
|
|
|
public function dashboard_widget_connect_to_wpcom() { |
6966
|
|
|
if ( Jetpack::is_active() || Jetpack::is_development_mode() || ! current_user_can( 'jetpack_connect' ) ) { |
6967
|
|
|
return; |
6968
|
|
|
} |
6969
|
|
|
?> |
6970
|
|
|
<div class="wpcom-connect"> |
6971
|
|
|
<div class="jp-emblem"> |
6972
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0" y="0" viewBox="0 0 172.9 172.9" enable-background="new 0 0 172.9 172.9" xml:space="preserve"> |
6973
|
|
|
<path d="M86.4 0C38.7 0 0 38.7 0 86.4c0 47.7 38.7 86.4 86.4 86.4s86.4-38.7 86.4-86.4C172.9 38.7 134.2 0 86.4 0zM83.1 106.6l-27.1-6.9C49 98 45.7 90.1 49.3 84l33.8-58.5V106.6zM124.9 88.9l-33.8 58.5V66.3l27.1 6.9C125.1 74.9 128.4 82.8 124.9 88.9z"/> |
6974
|
|
|
</svg> |
6975
|
|
|
</div> |
6976
|
|
|
<h3><?php esc_html_e( 'Please Connect Jetpack', 'jetpack' ); ?></h3> |
6977
|
|
|
<p><?php echo wp_kses( __( 'Connecting Jetpack will show you <strong>stats</strong> about your traffic, <strong>protect</strong> you from brute force attacks, <strong>speed up</strong> your images and photos, and enable other <strong>traffic and security</strong> features.', 'jetpack' ), 'jetpack' ) ?></p> |
6978
|
|
|
|
6979
|
|
|
<div class="actions"> |
6980
|
|
|
<a href="<?php echo $this->build_connect_url() ?>" class="button button-primary"> |
6981
|
|
|
<?php esc_html_e( 'Connect Jetpack', 'jetpack' ); ?> |
6982
|
|
|
</a> |
6983
|
|
|
</div> |
6984
|
|
|
</div> |
6985
|
|
|
<?php |
6986
|
|
|
} |
6987
|
|
|
|
6988
|
|
|
/* |
6989
|
|
|
* A graceful transition to using Core's site icon. |
6990
|
|
|
* |
6991
|
|
|
* All of the hard work has already been done with the image |
6992
|
|
|
* in all_done_page(). All that needs to be done now is update |
6993
|
|
|
* the option and display proper messaging. |
6994
|
|
|
* |
6995
|
|
|
* @todo remove when WP 4.3 is minimum |
|
|
|
|
6996
|
|
|
* |
6997
|
|
|
* @since 3.6.1 |
6998
|
|
|
* |
6999
|
|
|
* @return bool false = Core's icon not available || true = Core's icon is available |
7000
|
|
|
*/ |
7001
|
|
|
public static function jetpack_site_icon_available_in_core() { |
7002
|
|
|
global $wp_version; |
7003
|
|
|
$core_icon_available = function_exists( 'has_site_icon' ) && version_compare( $wp_version, '4.3-beta' ) >= 0; |
7004
|
|
|
|
7005
|
|
|
if ( ! $core_icon_available ) { |
7006
|
|
|
return false; |
7007
|
|
|
} |
7008
|
|
|
|
7009
|
|
|
// No need for Jetpack's site icon anymore if core's is already set |
7010
|
|
|
if ( has_site_icon() ) { |
7011
|
|
|
if ( Jetpack::is_module_active( 'site-icon' ) ) { |
7012
|
|
|
Jetpack::log( 'deactivate', 'site-icon' ); |
7013
|
|
|
Jetpack::deactivate_module( 'site-icon' ); |
7014
|
|
|
} |
7015
|
|
|
return true; |
7016
|
|
|
} |
7017
|
|
|
|
7018
|
|
|
// Transfer Jetpack's site icon to use core. |
7019
|
|
|
$site_icon_id = Jetpack::get_option( 'site_icon_id' ); |
7020
|
|
|
if ( $site_icon_id ) { |
7021
|
|
|
// Update core's site icon |
7022
|
|
|
update_option( 'site_icon', $site_icon_id ); |
7023
|
|
|
|
7024
|
|
|
// Delete Jetpack's icon option. We still want the blavatar and attached data though. |
7025
|
|
|
delete_option( 'site_icon_id' ); |
7026
|
|
|
} |
7027
|
|
|
|
7028
|
|
|
// No need for Jetpack's site icon anymore |
7029
|
|
|
if ( Jetpack::is_module_active( 'site-icon' ) ) { |
7030
|
|
|
Jetpack::log( 'deactivate', 'site-icon' ); |
7031
|
|
|
Jetpack::deactivate_module( 'site-icon' ); |
7032
|
|
|
} |
7033
|
|
|
|
7034
|
|
|
return true; |
7035
|
|
|
} |
7036
|
|
|
|
7037
|
|
|
} |
7038
|
|
|
|
The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using
the property is implicitly global.
To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.