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