Completed
Push — add/beta-plugin-code-standard ( cd9d7e...36bcad )
by
unknown
189:21 queued 179:48
created

Jetpack_Beta::proceed_to_install()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 16
nop 3
dl 0
loc 27
rs 8.8657
c 0
b 0
f 0
1
<?php
2
/**
3
 * Primary class file for the Jetpack Beta plugin.
4
 *
5
 * @package Jetpack Beta
6
 */
7
8
// Check that the file is not accessed directly.
9
if ( ! defined( 'ABSPATH' ) ) {
10
	exit;
11
}
12
13
/**
14
 * Class Jetpack_Beta
15
 */
16
class Jetpack_Beta {
17
18
	/**
19
	 * Singleton Jetpack_Beta class instance.
20
	 *
21
	 * @var Jetpack_Beta
22
	 */
23
	protected static $instance = null;
24
25
	/**
26
	 * WP Options string: jetpack_beta_active
27
	 *
28
	 * @var string
29
	 */
30
	protected static $option = 'jetpack_beta_active';
31
32
	/**
33
	 * WP Options string: jetpack_beta_dev_currently_installed
34
	 *
35
	 * @var string
36
	 */
37
	protected static $option_dev_installed = 'jetpack_beta_dev_currently_installed';
38
39
	/**
40
	 * WP Options string: jp_beta_autoupdate
41
	 *
42
	 * @var string
43
	 */
44
	protected static $option_autoupdate = 'jp_beta_autoupdate';
45
46
	/**
47
	 * WP Options string: jp_beta_email_notifications
48
	 *
49
	 * @var string
50
	 */
51
	protected static $option_email_notif = 'jp_beta_email_notifications';
52
53
	/**
54
	 * WP-Cron string: jetpack_beta_autoupdate_hourly_cron
55
	 *
56
	 * @var string
57
	 */
58
	protected static $auto_update_cron_hook = 'jetpack_beta_autoupdate_hourly_cron';
59
60
	/**
61
	 * Main Instance
62
	 */
63
	public static function instance() {
64
		if ( null === self::$instance ) {
65
			self::$instance = new self();
66
		}
67
68
		return self::$instance;
69
	}
70
71
	/**
72
	 * Constructor
73
	 */
74
	public function __construct() {
75
		if ( isset( $_GET['delete'] ) ) {
76
			delete_site_transient( 'update_plugins' );
77
		}
78
79
		add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'maybe_plugins_update_transient' ) );
80
		add_filter( 'upgrader_post_install', array( $this, 'upgrader_post_install' ), 10, 3 );
81
82
		add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ) );
83
		add_action( 'deactivate_plugin', array( $this, 'plugin_deactivated' ), 10, 2 );
84
85
		add_action( 'upgrader_process_complete', array( $this, 'upgrader_process_complete' ), 10, 2 );
86
87
		add_filter( 'plugin_action_links_' . JETPACK_PLUGIN_FILE, array( $this, 'remove_activate_stable' ) );
88
		add_filter( 'plugin_action_links_' . JETPACK_DEV_PLUGIN_FILE, array( $this, 'remove_activate_dev' ) );
89
90
		add_filter( 'network_admin_plugin_action_links_' . JETPACK_PLUGIN_FILE, array( $this, 'remove_activate_stable' ) );
91
		add_filter( 'network_admin_plugin_action_links_' . JETPACK_DEV_PLUGIN_FILE, array( $this, 'remove_activate_dev' ) );
92
93
		add_filter( 'all_plugins', array( $this, 'update_all_plugins' ) );
94
95
		add_filter( 'plugins_api', array( $this, 'get_plugin_info' ), 10, 3 );
96
97
		add_action( 'jetpack_beta_autoupdate_hourly_cron', array( 'Jetpack_Beta', 'run_autoupdate' ) );
98
99
		add_filter( 'jetpack_options_whitelist', array( $this, 'add_to_options_whitelist' ) );
100
101
		if ( is_admin() ) {
102
			require JPBETA__PLUGIN_DIR . 'jetpack-beta-admin.php';
103
			self::maybe_schedule_autoupdate();
104
			Jetpack_Beta_Admin::init();
105
		}
106
	}
107
108
	/**
109
	 * Fired when the upgrader process is complete; sets option jetpack_beta_dev_currently_installed
110
	 *
111
	 * @param WP_Upgrader $upgrader          - An upgrader instance.
112
	 * @param array       $updates_completed - Array of bulk item update data.
113
	 */
114
	public function upgrader_process_complete( $upgrader, $updates_completed ) {
115
		if ( ! isset( $updates_completed['plugins'] ) ) {
116
			return;
117
		}
118
119
		if ( 'update' === $updates_completed['action'] &&
120
			'plugin' === $updates_completed['type'] &&
121
		in_array( JETPACK_DEV_PLUGIN_FILE, $updates_completed['plugins'], true ) ) {
122
			list( $branch, $section ) = self::get_branch_and_section_dev();
123
			if ( self::should_update_dev_to_master() ) {
124
				list( $branch, $section ) = array( 'master', 'master' );
125
			}
126
			update_option( self::$option_dev_installed, array( $branch, $section, self::get_manifest_data( $branch, $section ) ) );
127
		}
128
	}
129
130
	/**
131
	 * If Jetpack or JP Dev plugin is network activated, update active_plugins option.
132
	 */
133
	public static function is_network_enabled() {
134
		if ( self::is_network_active() ) {
135
			add_filter( 'option_active_plugins', array( 'Jetpack_Beta', 'override_active_plugins' ) );
136
		}
137
	}
138
139
	/**
140
	 * This filter is only applied if Jetpack is network activated,
141
	 * makes sure that you can't have Jetpack or Jetpack Dev plugins versions loaded.
142
	 *
143
	 * @param array $active_plugins - Currently activated plugins.
144
	 *
145
	 * @return array Updated array of active plugins.
146
	 */
147
	public static function override_active_plugins( $active_plugins ) {
148
		$new_active_plugins = array();
149
		foreach ( $active_plugins as $active_plugin ) {
150
			if ( ! self::is_jetpack_plugin( $active_plugin ) ) {
151
				$new_active_plugins[] = $active_plugin;
152
			}
153
		}
154
		return $new_active_plugins;
155
	}
156
157
	/**
158
	 * Actions taken when the Jetpack Beta plugin is deactivated.
159
	 *
160
	 * @param string $plugin       - Plugin path being deactivated.
161
	 * @param bool   $network_wide - Whether the $plugin is being deactivated network wide.
162
	 */
163
	public function plugin_deactivated( $plugin, $network_wide ) {
164
		if ( ! self::is_jetpack_plugin( $plugin ) ) {
165
			return;
166
		}
167
168
		delete_option( self::$option );
169
	}
170
171
	/**
172
	 * Checks if passed plugin matches JP or JP Dev paths.
173
	 *
174
	 * @param string $plugin - A plugin path.
175
	 */
176
	public static function is_jetpack_plugin( $plugin ) {
177
		return in_array( $plugin, array( JETPACK_PLUGIN_FILE, JETPACK_DEV_PLUGIN_FILE ) );
178
	}
179
180
	/**
181
	 * Filter JP Dev plugin action links.
182
	 *
183
	 * @param array $actions - Array of plugin action links.
184
	 */
185
	public function remove_activate_dev( $actions ) {
186 View Code Duplication
		if ( is_plugin_active( JETPACK_PLUGIN_FILE ) || self::is_network_active() ) {
187
			$actions['activate'] = __( 'Plugin Already Active', 'jetpack-beta' );
188
		}
189
		return $actions;
190
	}
191
192
	/**
193
	 * Filter JP Stable plugin action links.
194
	 *
195
	 * @param array $actions - Array of plugin action links.
196
	 */
197
	public function remove_activate_stable( $actions ) {
198 View Code Duplication
		if ( is_plugin_active( JETPACK_DEV_PLUGIN_FILE ) || self::is_network_active() ) {
199
			$actions['activate'] = __( 'Plugin Already Active', 'jetpack-beta' );
200
		}
201
		return $actions;
202
	}
203
204
	/**
205
	 * Filters plugins to list in the Plugins list table.
206
	 *
207
	 * @param array $plugins - Array of arrays of plugin data.
208
	 *
209
	 * @return array Updated array of plugin data.
210
	 */
211
	public function update_all_plugins( $plugins ) {
212
		// WP.com requests away show regular plugin.
213
		if ( defined( 'REST_API_REQUEST' ) && REST_API_REQUEST ) {
214
			// Ensure that Jetpack reports the version it's using on account of the Jetpack Beta plugin to Calypso.
215
			if ( is_plugin_active( JETPACK_DEV_PLUGIN_FILE ) ) {
216
				$plugins[ JETPACK_PLUGIN_FILE ]['Version'] = $plugins[ JETPACK_DEV_PLUGIN_FILE ]['Version'];
217
			}
218
			unset( $plugins[ JETPACK_DEV_PLUGIN_FILE ] );
219
			return $plugins;
220
		}
221
222
		if ( is_plugin_active( JETPACK_DEV_PLUGIN_FILE ) ) {
223
			unset( $plugins[ JETPACK_PLUGIN_FILE ] );
224
		} else {
225
			unset( $plugins[ JETPACK_DEV_PLUGIN_FILE ] );
226
		}
227
		return $plugins;
228
	}
229
230
	public function get_plugin_info( $false, $action, $response ) {
231
232
		// Check if this call API is for the right plugin
233
		if ( ! isset( $response->slug ) || $response->slug != JETPACK_DEV_PLUGIN_SLUG ) {
234
			return false;
235
		}
236
		$update_date  = null;
237
		$download_zip = null;
238
		$dev_data     = self::get_dev_installed();
239
		if ( isset( $dev_data[2] ) ) {
240
			$update_date  = $dev_data[2]->update_date;
241
			$download_zip = $dev_data[2]->download_url;
242
		}
243
		// Update tags
244
		$response->slug          = JETPACK_DEV_PLUGIN_SLUG;
245
		$response->plugin        = JETPACK_DEV_PLUGIN_SLUG;
246
		$response->name          = 'Jetpack | ' . self::get_jetpack_plugin_pretty_version( true );
247
		$response->plugin_name   = 'Jetpack | ' . self::get_jetpack_plugin_pretty_version( true );
248
		$response->version       = self::get_jetpack_plugin_version( true );
249
		$response->author        = 'Automattic';
250
		$response->homepage      = 'https://jetpack.com/contact-support/beta-group/';
251
		$response->downloaded    = false;
252
		$response->last_updated  = $update_date;
253
		$response->sections      = array( 'description' => Jetpack_Beta_Admin::to_test_content() );
254
		$response->download_link = $download_zip;
255
		return $response;
256
	}
257
	/**
258
	 * Run on activation to flush update cache
259
	 */
260
	public static function activate() {
261
		// don't do anyting funnly
262
		if ( defined( 'DOING_CRON' ) ) {
263
			return;
264
		}
265
		delete_site_transient( 'update_plugins' );
266
	}
267
268
	public static function get_plugin_file() {
269
		return self::get_plugin_slug() . '/jetpack.php';
270
	}
271
272
	public static function get_plugin_slug() {
273
		$installed = self::get_branch_and_section();
274
		if ( empty( $installed ) || $installed[1] === 'stable' || $installed[1] === 'tags' ) {
275
			return 'jetpack';
276
		}
277
		return JETPACK_DEV_PLUGIN_SLUG;
278
	}
279
280
	public static function deactivate() {
281
		// don't do anyting funnly
282
		if ( defined( 'DOING_CRON' ) ) {
283
			return;
284
		}
285
286
		self::clear_autoupdate_cron();
287
		self::delete_all_transiants();
288
		add_action( 'shutdown', array( __CLASS__, 'switch_active' ), 5 );
289
		add_action( 'shutdown', array( __CLASS__, 'remove_dev_plugin' ), 20 );
290
		delete_option( self::$option );
291
	}
292
293
	static function remove_dev_plugin() {
294
		if ( is_multisite() ) {
295
			return;
296
		}
297
298
		// Delete the jetpack dev plugin
299
		require_once ABSPATH . 'wp-admin/includes/file.php';
300
		$creds = request_filesystem_credentials( site_url() . '/wp-admin/', '', false, false, array() );
301
		if ( ! WP_Filesystem( $creds ) ) {
302
			/* any problems and we exit */
303
			return;
304
		}
305
		global $wp_filesystem;
306
		if ( ! $wp_filesystem ) {
307
			return;
308
		}
309
310
		$working_dir = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . JETPACK_DEV_PLUGIN_SLUG;
311
		// delete the folder JETPACK_BETA_PLUGIN_FOLDER
312
		if ( $wp_filesystem->is_dir( $working_dir ) ) {
313
			$wp_filesystem->delete( $working_dir, true );
314
		}
315
		// Since we are removing this dev plugin we should also clean up this data.
316
		delete_option( self::$option_dev_installed );
317
	}
318
319
	static function admin_url( $query = '?page=jetpack-beta' ) {
320
		return ( self::is_network_active() )
321
		? network_admin_url( 'admin.php' . $query )
322
		: admin_url( 'admin.php' . $query );
323
	}
324
325
	public function admin_bar_menu() {
326
		global $wp_admin_bar;
327
328
		if ( ! is_object( $wp_admin_bar ) ) {
329
			return;
330
		}
331
332
		// Nothing got activated yet.
333
		if ( ! self::get_option() ) {
334
			return;
335
		}
336
337
		$args = array(
338
			'id'     => 'jetpack-beta_admin_bar',
339
			'title'  => 'Jetpack Beta',
340
			'parent' => 'top-secondary',
341
			'href'   => current_user_can( 'update_plugins' ) ? self::admin_url() : '',
342
		);
343
		$wp_admin_bar->add_node( $args );
344
345
		// add a child item to our parent item
346
		$args = array(
347
			'id'     => 'jetpack-beta_version',
348
			'title'  => sprintf( __( 'Running %s', 'jetpack-beta' ), self::get_jetpack_plugin_pretty_version() ),
349
			'parent' => 'jetpack-beta_admin_bar',
350
		);
351
352
		$wp_admin_bar->add_node( $args );
353
354
		if ( self::get_plugin_slug() === JETPACK_DEV_PLUGIN_SLUG ) {
355
			// Highlight the menu if you are running the BETA Versions..
356
			echo sprintf( '<style>#wpadminbar #wp-admin-bar-jetpack-beta_admin_bar { background: %s; }</style>', JETPACK_GREEN );
357
		}
358
359
		$args = array(
360
			'id'     => 'jetpack-beta_report',
361
			'title'  => __( 'Report Bug', 'jetpack-beta' ),
362
			'href'   => JETPACK_BETA_REPORT_URL,
363
			'parent' => 'jetpack-beta_admin_bar',
364
		);
365
		$wp_admin_bar->add_node( $args );
366
367
		list( $branch, $section ) = self::get_branch_and_section();
368
		if ( 'pr' === $section ) {
369
			$args = array(
370
				'id'     => 'jetpack-beta_report_more_info',
371
				'title'  => __( 'More Info ', 'jetpack-beta' ),
372
				'href'   => self::get_url( $branch, $section ),
373
				'parent' => 'jetpack-beta_admin_bar',
374
			);
375
			$wp_admin_bar->add_node( $args );
376
		}
377
	}
378
379
	public function maybe_plugins_update_transient( $transient ) {
380
		if ( ! isset( $transient->no_update ) ) {
381
			return $transient;
382
		}
383
384
		// Do not try to update things that do not exist
385
		if ( ! file_exists( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . JETPACK_DEV_PLUGIN_FILE ) ) {
386
			return $transient;
387
		}
388
389
		// Do not look for update if we are stable branch
390
		if ( self::is_on_stable() ) {
391
			return $transient;
392
		}
393
394
		// Lets always grab the latest
395
		delete_site_transient( 'jetpack_beta_manifest' );
396
397
		// check if there is a new version
398
		if ( self::should_update_dev_to_master() ) {
399
			// If response is false, don't alter the transient
400
			$transient->response[ JETPACK_DEV_PLUGIN_FILE ] = self::get_jepack_dev_master_update_response();
401
			// unset the that it doesn't need an update...
402
			unset( $transient->no_update[ JETPACK_DEV_PLUGIN_FILE ] );
403
		} elseif ( self::should_update_dev_version() ) {
404
			// If response is false, don't alter the transient
405
			$transient->response[ JETPACK_DEV_PLUGIN_FILE ] = self::get_jepack_dev_update_response();
406
			// unset the that it doesn't need an update...
407
			unset( $transient->no_update[ JETPACK_DEV_PLUGIN_FILE ] );
408
		} else {
409
			unset( $transient->response[ JETPACK_DEV_PLUGIN_FILE ] );
410
			if ( isset( $transient->no_update ) ) {
411
				$transient->no_update[ JETPACK_DEV_PLUGIN_FILE ] = self::get_jepack_dev_update_response();
412
			}
413
		}
414
415
		return $transient;
416
	}
417
418
	static function should_update_dev_version() {
419
		return version_compare( self::get_new_jetpack_version( true ), self::get_jetpack_plugin_version( true ), '>' );
420
	}
421
422
	static function get_jepack_dev_update_response() {
423
		$response              = new stdClass();
424
		$response->id          = JETPACK_DEV_PLUGIN_SLUG;
425
		$response->plugin      = JETPACK_DEV_PLUGIN_SLUG;
426
		$response->new_version = self::get_new_jetpack_version( true );
427
		$response->slug        = JETPACK_DEV_PLUGIN_SLUG;
428
		$response->url         = self::get_url_dev();
429
		$response->package     = self::get_install_url_dev();
430
		return $response;
431
	}
432
433
	static function get_jepack_dev_master_update_response() {
434
		$response = self::get_jepack_dev_update_response();
435
436
		$master_manifest       = self::get_manifest_data( 'master', 'master' );
437
		$response->new_version = $master_manifest->version;
438
		$response->url         = self::get_url( 'master', 'master' );
439
		$response->package     = $master_manifest->download_url;
440
		return $response;
441
	}
442
443
	/**
444
	 * Moves the newly downloaded folder into jetpack-dev
445
	 *
446
	 * @param $worked
447
	 * @param $hook_extras
448
	 * @param $result
449
	 *
450
	 * @return WP_Error
451
	 */
452
	public function upgrader_post_install( $worked, $hook_extras, $result ) {
453
		global $wp_filesystem;
454
455
		if (
456
		! isset( $hook_extras['plugin'] )
457
		|| JETPACK_DEV_PLUGIN_FILE !== $hook_extras['plugin']
458
		) {
459
			return $worked;
460
		}
461
462
		if ( $wp_filesystem->move( $result['destination'], WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . JETPACK_DEV_PLUGIN_SLUG, true ) ) {
463
			return $worked;
464
		} else {
465
			return new WP_Error();
466
		}
467
	}
468
469
	static function get_jetpack_plugin_version( $is_dev_version = false ) {
470
		if ( $is_dev_version ) {
471
			$info = self::get_jetpack_plugin_info_dev();
472
		} else {
473
			$info = self::get_jetpack_plugin_info();
474
		}
475
476
		return isset( $info['Version'] ) ? $info['Version'] : 0;
477
	}
478
479
	static function get_option() {
480
		return get_option( self::$option );
481
	}
482
483
	static function get_dev_installed() {
484
		return get_option( self::$option_dev_installed );
485
	}
486
487
	static function get_branch_and_section() {
488
		$option = (array) self::get_option();
489
		if ( false === $option[0] ) {
490
			// see if the jetpack is plugin enabled
491
			if ( is_plugin_active( JETPACK_PLUGIN_FILE ) ) {
492
				return array( 'stable', 'stable' );
493
			}
494
			return array( false, false );
495
		}
496
		// branch and section
497
		return $option;
498
	}
499
500
	static function is_on_stable() {
501
		$branch_and_section = self::get_branch_and_section();
502
		if ( empty( $branch_and_section[0] ) || $branch_and_section[0] == 'stable' ) {
503
			return true;
504
		}
505
		return false;
506
	}
507
508
	static function is_on_tag() {
509
		$option = (array) self::get_option();
510
		if ( isset( $option[1] ) && 'tags' === $option[1] ) {
511
			return true;
512
		}
513
		return false;
514
	}
515
516
	static function get_branch_and_section_dev() {
517
		$option = (array) self::get_dev_installed();
518
		if ( false !== $option[0] && isset( $option[1] ) ) {
519
			return array( $option[0], $option[1] );
520
		}
521
		if ( is_plugin_active( JETPACK_DEV_PLUGIN_FILE ) ) {
522
			return array( 'stable', 'stable' );
523
		}
524
		return array( false, false );
525
	}
526
527
	static function get_jetpack_plugin_pretty_version( $is_dev_version = false ) {
528
		if ( $is_dev_version ) {
529
			list( $branch, $section ) = self::get_branch_and_section_dev();
530
		} else {
531
			list( $branch, $section ) = self::get_branch_and_section();
532
		}
533
534
		if ( ! $section ) {
535
			return '';
536
		}
537
538
		if ( 'master' === $section ) {
539
			return 'Bleeding Edge';
540
		}
541
542
		if ( 'stable' === $section ) {
543
			return 'Latest Stable';
544
		}
545
546
		if ( 'tags' === $section ) {
547
			return sprintf(
548
				__( 'Public release (<a href="https://plugins.trac.wordpress.org/browser/jetpack/tags/%1$s" target="_blank" rel="noopener noreferrer">available on WordPress.org</a>)', 'jetpack-beta' ),
549
				esc_attr( $branch )
550
			);
551
		}
552
553
		if ( 'rc' === $section ) {
554
			return 'Release Candidate';
555
		}
556
557
		if ( 'pr' === $section ) {
558
			$branch = str_replace( '-', ' ', $branch );
559
			return 'Feature Branch: ' . str_replace( '_', ' / ', $branch );
560
		}
561
562
		return self::get_jetpack_plugin_version();
563
	}
564
565
	static function get_new_jetpack_version( $is_dev_version = false ) {
566
		$manifest = self::get_beta_manifest();
567
		if ( $is_dev_version ) {
568
			list( $branch, $section ) = self::get_branch_and_section_dev();
569
		} else {
570
			list( $branch, $section ) = self::get_branch_and_section();
571
		}
572
573
		if ( 'master' === $section && isset( $manifest->{$section}->version ) ) {
574
			return $manifest->{$section}->version;
575
		}
576
577
		if ( 'rc' === $section && isset( $manifest->{$section}->version ) ) {
578
			return $manifest->{$section}->version;
579
		}
580
581
		if ( isset( $manifest->{$section} ) &&
582
		isset( $manifest->{$section}->{$branch} ) &&
583
		isset( $manifest->{$section}->{$branch}->version )
584
		) {
585
			return $manifest->{$section}->{$branch}->version;
586
		}
587
		return 0;
588
	}
589
590
	static function get_url_dev() {
591
		list( $branch, $section ) = self::get_branch_and_section_dev();
592
		return self::get_url( $branch, $section );
593
	}
594
595
	static function get_url( $branch = null, $section = null ) {
596
		if ( is_null( $section ) ) {
597
			list( $branch, $section ) = self::get_branch_and_section();
598
		}
599
600
		if ( 'master' === $section ) {
601
			return JETPACK_GITHUB_URL . '/tree/master-build';
602
		}
603
604
		if ( 'rc' === $section ) {
605
			return JETPACK_GITHUB_URL . '/tree/' . $section . '-build';
606
		}
607
608
		if ( 'pr' === $section ) {
609
			$manifest = self::get_beta_manifest();
610
			return isset( $manifest->{$section}->{$branch}->pr )
611
			? JETPACK_GITHUB_URL . '/pull/' . $manifest->{$section}->{$branch}->pr
612
			: JETPACK_DEFAULT_URL;
613
		}
614
		return JETPACK_DEFAULT_URL;
615
	}
616
617
	static function get_install_url_dev() {
618
		list( $branch, $section ) = self::get_branch_and_section_dev();
619
		return self::get_install_url( $branch, $section );
620
	}
621
622
	static function get_install_url( $branch = null, $section = null ) {
623
		if ( is_null( $section ) ) {
624
			list( $branch, $section ) = self::get_branch_and_section();
625
		}
626
627
		if ( 'stable' === $section ) {
628
			$org_data = self::get_org_data();
629
			return $org_data->download_link;
630
		} elseif ( 'tags' === $section ) {
631
			$org_data = self::get_org_data();
632
			return $org_data->versions->{$branch} ?: false;
633
		}
634
		$manifest = self::get_beta_manifest( true );
635
636
		if ( 'master' === $section && isset( $manifest->{$section}->download_url ) ) {
637
			return $manifest->{$section}->download_url;
638
		}
639
640
		if ( 'rc' === $section ) {
641
			if ( isset( $manifest->{$section}->download_url ) ) {
642
				return $manifest->{$section}->download_url;
643
			}
644
			$branches = array_keys( (array) $manifest->{$section} );
645
			foreach ( $branches as $branch ) {
646
				if ( isset( $manifest->{$section}->{$branch}->download_url ) ) {
647
					return $manifest->{$section}->{$branch}->download_url;
648
				}
649
			}
650
			return null;
651
		}
652
653
		if ( isset( $manifest->{$section}->{$branch}->download_url ) ) {
654
			return $manifest->{$section}->{$branch}->download_url;
655
		}
656
		return null;
657
	}
658
659
	static function get_jetpack_plugin_info_stable() {
660
		return self::get_jetpack_plugin_info( JETPACK_PLUGIN_FILE );
661
	}
662
663
	static function get_jetpack_plugin_info_dev() {
664
		return self::get_jetpack_plugin_info( JETPACK_DEV_PLUGIN_FILE );
665
	}
666
667
	static function get_jetpack_plugin_info( $plugin_file = null ) {
668
669
		if ( is_null( $plugin_file ) ) {
670
			$plugin_file = self::get_plugin_file();
671
		}
672
673
		if ( ! function_exists( 'get_plugin_data' ) ) {
674
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
675
		}
676
		$plugin_file_path = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $plugin_file;
677
678
		if ( file_exists( $plugin_file_path ) ) {
679
			return get_plugin_data( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $plugin_file );
680
		}
681
682
		return null;
683
	}
684
685
	/*
686
	* This needs to happen on shutdown. Other wise it doesn't work.
687
	*/
688
	static function switch_active() {
689
		self::replace_active_plugin( JETPACK_DEV_PLUGIN_FILE, JETPACK_PLUGIN_FILE );
690
	}
691
692
	static function get_beta_manifest( $force_refresh = false ) {
693
		return self::get_remote_data( JETPACK_BETA_MANIFEST_URL, 'manifest', $force_refresh );
694
	}
695
696
	static function get_org_data() {
697
		return self::get_remote_data( JETPACK_ORG_API_URL, 'org_data' );
698
	}
699
700
	static function get_remote_data( $url, $transient, $bypass = false ) {
701
		$prefix = 'jetpack_beta_';
702
		$cache  = get_site_transient( $prefix . $transient );
703
		if ( $cache && ! $bypass ) {
704
			return $cache;
705
		}
706
707
		$remote_manifest = wp_remote_get( $url );
708
709
		if ( is_wp_error( $remote_manifest ) ) {
710
			return false;
711
		}
712
713
		$cache = json_decode( wp_remote_retrieve_body( $remote_manifest ) );
714
		set_site_transient( $prefix . $transient, $cache, MINUTE_IN_SECONDS * 15 );
715
716
		return $cache;
717
	}
718
719
	static function delete_all_transiants() {
720
		$prefix = 'jetpack_beta_';
721
722
		delete_site_transient( $prefix . 'org_data' );
723
		delete_site_transient( $prefix . 'manifest' );
724
725
		delete_site_transient( Jetpack_Beta_Autoupdate_Self::TRANSIENT_NAME );
726
727
	}
728
729
	static function install_and_activate( $branch, $section ) {
730
731
		// Clean up previous version of the beta plugin
732
		if ( file_exists( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . 'jetpack-pressable-beta' ) ) {
733
			// Delete the jetpack dev plugin
734
			require_once ABSPATH . 'wp-admin/includes/file.php';
735
			$creds = request_filesystem_credentials( site_url() . '/wp-admin/', '', false, false, array() );
736
			if ( ! WP_Filesystem( $creds ) ) {
737
				/* any problems and we exit */
738
				return new WP_error( 'Filesystem Problem' );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'Filesystem Problem'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
739
			}
740
			global $wp_filesystem;
741
			if ( ! $wp_filesystem ) {
742
				return new WP_error( '$wp_filesystem is not global' );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with '$wp_filesystem is not global'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
743
			}
744
745
			$working_dir = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . 'jetpack-pressable-beta';
746
			// delete the folder JETPACK_BETA_PLUGIN_FOLDER
747
			if ( $wp_filesystem->is_dir( $working_dir ) ) {
748
				$wp_filesystem->delete( $working_dir, true );
749
			}
750
			// Deactivate the plugin
751
			self::replace_active_plugin( 'jetpack-pressable-beta/jetpack.php' );
752
		}
753
754 View Code Duplication
		if ( 'stable' === $section &&
755
		file_exists( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . JETPACK_PLUGIN_FILE ) ) {
756
			self::replace_active_plugin( JETPACK_DEV_PLUGIN_FILE, JETPACK_PLUGIN_FILE, true );
757
			self::update_option( $branch, $section );
758
			return;
759
		}
760
761 View Code Duplication
		if ( self::get_branch_and_section_dev() === array( $branch, $section )
762
		&& file_exists( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . JETPACK_DEV_PLUGIN_FILE ) ) {
763
			self::replace_active_plugin( JETPACK_PLUGIN_FILE, JETPACK_DEV_PLUGIN_FILE, true );
764
			self::update_option( $branch, $section );
765
			return;
766
		}
767
768
		self::proceed_to_install_and_activate(
769
			self::get_install_url( $branch, $section ),
770
			self::get_plugin_slug( $section ),
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Beta::get_plugin_slug() has too many arguments starting with $section.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
771
			$section
772
		);
773
		self::update_option( $branch, $section );
774
		return;
775
	}
776
777
	static function update_plugin( $branch, $section ) {
778
		self::proceed_to_install(
779
			self::get_install_url( $branch, $section ),
780
			self::get_plugin_slug( $section ),
0 ignored issues
show
Unused Code introduced by
The call to Jetpack_Beta::get_plugin_slug() has too many arguments starting with $section.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
781
			$section
782
		);
783
784 View Code Duplication
		if ( $section !== 'stable' ) {
785
			update_option( self::$option_dev_installed, array( $branch, $section, self::get_manifest_data( $branch, $section ) ) );
786
		}
787
		return;
788
	}
789
790
	static function update_option( $branch, $section ) {
791 View Code Duplication
		if ( 'stable' !== $section ) {
792
			update_option( self::$option_dev_installed, array( $branch, $section, self::get_manifest_data( $branch, $section ) ) );
793
		}
794
		update_option( self::$option, array( $branch, $section ) );
795
	}
796
797
	static function get_manifest_data( $branch, $section ) {
798
		$installed             = get_option( self::$option_dev_installed );
799
		$current_manifest_data = isset( $installed[2] ) ? $installed[2] : false;
800
801
		$manifest_data = self::get_beta_manifest();
802
803
		if ( ! isset( $manifest_data->{$section} ) ) {
804
			return $current_manifest_data;
805
		}
806
807
		if ( 'master' === $section ) {
808
			return $manifest_data->{$section};
809
		}
810
811
		if ( 'rc' === $section ) {
812
			return $manifest_data->{$section};
813
		}
814
815
		if ( isset( $manifest_data->{$section}->{$branch} ) ) {
816
			return $manifest_data->{$section}->{$branch};
817
		}
818
819
		return $current_manifest_data;
820
	}
821
822
	static function proceed_to_install_and_activate( $url, $plugin_folder = JETPACK_DEV_PLUGIN_SLUG, $section ) {
823
		self::proceed_to_install( $url, $plugin_folder, $section );
824
825
		if ( 'stable' === $section || 'tags' === $section ) {
826
			self::replace_active_plugin( JETPACK_DEV_PLUGIN_FILE, JETPACK_PLUGIN_FILE, true );
827
		} else {
828
			self::replace_active_plugin( JETPACK_PLUGIN_FILE, JETPACK_DEV_PLUGIN_FILE, true );
829
		}
830
	}
831
832
	static function proceed_to_install( $url, $plugin_folder = JETPACK_DEV_PLUGIN_SLUG, $section ) {
833
		$temp_path = download_url( $url );
834
835
		if ( is_wp_error( $temp_path ) ) {
836
			wp_die( sprintf( __( 'Error Downloading: <a href="%1$s">%1$s</a> - Error: %2$s', 'jetpack-beta' ), $url, $temp_path->get_error_message() ) );
837
		}
838
		require_once ABSPATH . 'wp-admin/includes/file.php';
839
		$creds = request_filesystem_credentials( site_url() . '/wp-admin/', '', false, false, array() );
840
		/* initialize the API */
841
		if ( ! WP_Filesystem( $creds ) ) {
842
			/* any problems and we exit */
843
			wp_die( __( 'Jetpack Beta: No File System access', 'jetpack-beta' ) );
844
		}
845
846
		global $wp_filesystem;
847
		if ( 'stable' === $section || 'tags' === $section ) {
848
			$plugin_path = WP_PLUGIN_DIR;
849
		} else {
850
			$plugin_path = str_replace( ABSPATH, $wp_filesystem->abspath(), WP_PLUGIN_DIR );
851
		}
852
853
		$result = unzip_file( $temp_path, $plugin_path );
854
855
		if ( is_wp_error( $result ) ) {
856
			wp_die( sprintf( __( 'Error Unziping file: Error: %1$s', 'jetpack-beta' ), $result->get_error_message() ) );
857
		}
858
	}
859
860
	static function is_network_active() {
861
		if ( ! is_multisite() ) {
862
			return false;
863
		}
864
865
		if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
866
			return false;
867
		}
868
869
		if ( is_plugin_active_for_network( JETPACK_PLUGIN_FILE ) || is_plugin_active_for_network( JETPACK_DEV_PLUGIN_FILE ) ) {
870
			return true;
871
		}
872
873
		return false;
874
	}
875
876
	static function replace_active_plugin( $current_plugin, $replace_with_plugin = null, $force_activate = false ) {
877
		if ( self::is_network_active() ) {
878
			$new_active_plugins     = array();
879
			$network_active_plugins = get_site_option( 'active_sitewide_plugins' );
880
			foreach ( $network_active_plugins as $plugin => $date ) {
881
				$key                        = ( $plugin === $current_plugin ? $replace_with_plugin : $plugin );
882
				$new_active_plugins[ $key ] = $date;
883
			}
884
			update_site_option( 'active_sitewide_plugins', $new_active_plugins );
885
			return;
886
		}
887
888
		$active_plugins     = (array) get_option( 'active_plugins', array() );
889
		$new_active_plugins = array();
890
891
		if ( empty( $replace_with_plugin ) ) {
892
			$new_active_plugins = array_diff( $active_plugins, array( $current_plugin ) );
893
		} else {
894
			foreach ( $active_plugins as $plugin ) {
895
				$new_active_plugins[] = ( $plugin === $current_plugin ? $replace_with_plugin : $plugin );
896
			}
897
		}
898
899
		if ( $force_activate && ! in_array( $replace_with_plugin, $new_active_plugins ) ) {
900
			$new_active_plugins[] = $replace_with_plugin;
901
		}
902
		update_option( 'active_plugins', $new_active_plugins );
903
	}
904
905
	static function should_update_stable_version() {
906
		// Pressable Jetpack version is manage via Pressable
907
		if ( defined( 'IS_PRESSABLE' ) && IS_PRESSABLE ) {
908
			return false;
909
		}
910
		// Check if we are Jetpack plugin is installed via git
911
		if ( file_exists( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . 'jetpack/.git' ) ) {
912
			return false;
913
		}
914
915
		// Check if running a tag directly from svn
916
		if ( self::is_on_tag() ) {
917
			return false;
918
		}
919
920
		$updates = get_site_transient( 'update_plugins' );
921
922
		if ( isset( $updates->response, $updates->response[ JETPACK_PLUGIN_FILE ] ) ) {
923
			return true;
924
		}
925
		$org_data    = self::get_org_data();
926
		$plugin_data = self::get_jetpack_plugin_info_stable();
927
928
		return ( isset( $plugin_data['Version'], $org_data->version )
929
			&& $org_data->version !== $plugin_data['Version'] );
930
	}
931
932
	/**
933
	 * Here we are checking if the DEV branch that we are currenly on is not something that is available in the manifest
934
	 * Meaning that the DEV branch was merged into master and so we need to update it.
935
	 *
936
	 * @return bool
937
	 */
938
	static function should_update_dev_to_master() {
939
		list( $branch, $section ) = self::get_branch_and_section_dev();
940
941
		if ( false === $branch || 'master' === $section || 'rc' === $section || 'tags' === $section ) {
942
			return false;
943
		}
944
		$manifest = self::get_beta_manifest();
945
		return ! isset( $manifest->{$section}->{$branch} );
946
	}
947
948
	static function is_set_to_autoupdate() {
949
		return get_option( 'jp_beta_autoupdate', false );
950
	}
951
952
	static function is_set_to_email_notifications() {
953
		return get_option( 'jp_beta_email_notifications', true );
954
	}
955
956
	static function clear_autoupdate_cron() {
957
		if ( ! is_main_site() ) {
958
			return;
959
		}
960
		wp_clear_scheduled_hook( self::$auto_update_cron_hook );
961
962
		if ( function_exists( 'wp_unschedule_hook' ) ) { // new in WP 4.9
963
			wp_unschedule_hook( self::$auto_update_cron_hook );
964
		}
965
	}
966
967
	static function schedule_hourly_autoupdate() {
968
		wp_clear_scheduled_hook( self::$auto_update_cron_hook );
969
		wp_schedule_event( time(), 'hourly', self::$auto_update_cron_hook );
970
	}
971
972
	static function maybe_schedule_autoupdate() {
973
		if ( ! self::is_set_to_autoupdate() ) {
974
			return;
975
		}
976
977
		if ( ! is_main_site() ) {
978
			return;
979
		}
980
		$has_schedule_already = wp_get_schedule( self::$auto_update_cron_hook );
981
		if ( ! $has_schedule_already ) {
982
			self::schedule_hourly_autoupdate();
983
		}
984
	}
985
986
	static function what_changed() {
987
		if ( $commit = self::get_version_commit() ) {
988
			$html        = '';
989
			$commit_data = self::get_commit_data_from_github( $commit );
990
			if ( isset( $commit_data->commit->message ) ) {
991
				$html .= sprintf(
992
					__( "\n %1\$s \n\n[Commit](%2\$s)", 'jetpack-beta' ),
993
					esc_html( $commit_data->commit->message ),
994
					esc_url( $commit_data->html_url )
995
				);
996
				"\n\n";
997
			}
998
			if ( ! empty( $commit_data->files ) ) {
999
				$html .= "\n\n";
1000
				$html .= sprintf( _n( 'One file changed ', '%d files changed', count( $commit_data->files ), 'jetpack-beta' ), count( $commit_data->files ) );
1001
				$html .= "\n";
1002
				foreach ( $commit_data->files as $file ) {
1003
					$added_deleted_changed = array();
1004
					if ( $file->additions ) {
1005
						$added_deleted_changed[] = '+' . $file->additions;
1006
					}
1007
					if ( $file->deletions ) {
1008
						$added_deleted_changed[] = '-' . $file->deletions;
1009
					}
1010
					$html .= sprintf( "- %s ... (%s %s) \n", esc_html( $file->filename ), esc_html( $file->status ), implode( ' ', $added_deleted_changed ) );
1011
				}
1012
				$html .= "\n\n";
1013
			}
1014
			if ( ! empty( $html ) ) {
1015
				return $html;
1016
			}
1017
		}
1018
		return false;
1019
	}
1020
1021
	static function get_version_commit() {
1022
		$split_version = explode( '-', self::get_jetpack_plugin_version() );
1023
		if ( isset( $split_version[3] ) ) {
1024
			return $split_version[3];
1025
		}
1026
		return false;
1027
	}
1028
1029
	static function get_commit_data_from_github( $commit ) {
1030
		return self::get_remote_data( JETPACK_GITHUB_API_URL . 'commits/' . $commit, 'github_commits_' . $commit );
1031
	}
1032
1033
	static function run_autoupdate() {
1034
		if ( ! self::is_set_to_autoupdate() ) {
1035
			return;
1036
		}
1037
1038
		if ( ! is_main_site() ) {
1039
			return;
1040
		}
1041
1042
		require_once ABSPATH . 'wp-admin/includes/file.php';
1043
		require_once ABSPATH . 'wp-admin/includes/plugin.php';
1044
		require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
1045
		wp_clean_plugins_cache();
1046
		ob_start();
1047
		wp_update_plugins(); // Check for Plugin updates
1048
		ob_end_clean();
1049
		$plugins = array();
1050
		if (
1051
		! self::is_on_stable() &&
1052
		( self::should_update_dev_to_master() || self::should_update_dev_version() )
1053
		) {
1054
			add_filter( 'upgrader_source_selection', array( 'Jetpack_Beta', 'check_for_main_files' ), 10, 2 );
1055
1056
			// If response is false, don't alter the transient
1057
			$plugins[] = JETPACK_DEV_PLUGIN_FILE;
1058
		}
1059
		$autupdate = Jetpack_Beta_Autoupdate_Self::instance();
1060
		if ( $autupdate->has_never_version() ) {
1061
			$plugins[] = JPBETA__PLUGIN_FOLDER . '/jetpack-beta.php';
1062
		}
1063
1064
		if ( empty( $plugins ) ) {
1065
			return;
1066
		}
1067
1068
		// unhook this functions that output things before we send our response header.
1069
		remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
1070
		remove_action( 'upgrader_process_complete', 'wp_version_check' );
1071
		remove_action( 'upgrader_process_complete', 'wp_update_themes' );
1072
1073
		$skin = new WP_Ajax_Upgrader_Skin();
1074
		// The Automatic_Upgrader_Skin skin shouldn't output anything.
1075
		$upgrader = new Plugin_Upgrader( $skin );
1076
		$upgrader->init();
1077
		// This avoids the plugin to be deactivated.
1078
		// Using bulk upgrade puts the site into maintenance mode during the upgrades
1079
		$result = $upgrader->bulk_upgrade( $plugins );
1080
		$errors = $upgrader->skin->get_errors();
1081
		$log    = $upgrader->skin->get_upgrade_messages();
1082
1083
		if ( is_wp_error( $errors ) && $errors->get_error_code() ) {
1084
			return $errors;
1085
		}
1086
1087
		if ( $result && ! defined( 'JETPACK_BETA_SKIP_EMAIL' ) && self::is_set_to_email_notifications() ) {
1088
			self::send_autoupdate_email( $plugins, $log );
1089
		}
1090
	}
1091
1092
	/**
1093
	 * Builds and sends an email about succesfull plugin autoupdate
1094
	 *
1095
	 * @param Array  $plugins List of plugins that were updated.
1096
	 * @param String $log upgrade message from core's plugin upgrader.
1097
	 */
1098
	private static function send_autoupdate_email( $plugins, $log ) {
1099
		$admin_email = get_site_option( 'admin_email' );
1100
1101
		if ( empty( $admin_email ) ) {
1102
			return;
1103
		}
1104
1105
		// In case the code is called in a scope different from wp-admin.
1106
		require_once JPBETA__PLUGIN_DIR . 'jetpack-beta-admin.php';
1107
1108
		// Calling empty() on a function return value crashes in PHP < 5.5.
1109
		// Thus we assign the return value explicitly and then check with empty().
1110
		$bloginfo_name = get_bloginfo( 'name' );
1111
		$site_title    = ! empty( $bloginfo_name ) ? get_bloginfo( 'name' ) : get_site_url();
1112
		$what_updated  = 'Jetpack Beta Tester Plugin';
1113
		$subject       = sprintf( __( '[%s] Autoupdated Jetpack Beta Tester', 'jetpack-beta' ), $site_title );
1114
1115
		if ( in_array( JETPACK_DEV_PLUGIN_FILE, $plugins, true ) ) {
1116
			$subject = sprintf(
1117
				__( '[%1$s] Autoupdated Jetpack %2$s ', 'jetpack-beta' ),
1118
				$site_title,
1119
				self::get_jetpack_plugin_pretty_version()
1120
			);
1121
1122
			$what_updated = sprintf(
1123
				__( 'Jetpack %1$s (%2$s)', 'jetpack-beta' ),
1124
				self::get_jetpack_plugin_pretty_version(),
1125
				self::get_jetpack_plugin_version()
1126
			);
1127
1128
			if ( count( $plugins ) > 1 ) {
1129
				$subject = sprintf(
1130
					__( '[%1$s] Autoupdated Jetpack %2$s and the Jetpack Beta Tester', 'jetpack-beta' ),
1131
					$site_title,
1132
					self::get_jetpack_plugin_pretty_version()
1133
				);
1134
1135
				$what_updated = sprintf(
1136
					__( 'Jetpack %1$s (%2$s) and the Jetpack Beta Tester', 'jetpack-beta' ),
1137
					self::get_jetpack_plugin_pretty_version(),
1138
					self::get_jetpack_plugin_version()
1139
				);
1140
			}
1141
		}
1142
1143
		$message  = sprintf(
1144
			__( 'Howdy! Your site at %1$s has autoupdated %2$s.', 'jetpack-beta' ),
1145
			home_url(),
1146
			$what_updated
1147
		);
1148
		$message .= "\n\n";
1149
1150
		$what_changed = self::what_changed();
1151
		if ( $what_changed ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $what_changed of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1152
			$message .= __( 'What changed?', 'jetpack-beta' );
1153
			$message .= wp_strip_all_tags( $what_changed );
1154
		}
1155
1156
		$message .= __( 'During the autoupdate the following happened:', 'jetpack-beta' );
1157
		$message .= "\n\n";
1158
		// Can only reference the About screen if their update was successful.
1159
		$log      = array_map( 'html_entity_decode', $log );
1160
		$message .= ' - ' . implode( "\n - ", $log );
1161
		$message .= "\n\n";
1162
1163
		// Adds To test section. for PR's it's a PR description, for master/RC - it's a to_test.md file contents.
1164
		$message .= Jetpack_Beta_Admin::to_test_content();
1165
		$message .= "\n\n";
1166
1167
		wp_mail( $admin_email, $subject, $message );
1168
	}
1169
1170
	/**
1171
	 * This checks intends to fix errors in our build server when jetpack
1172
	 *
1173
	 * @param $source
1174
	 * @param $remote_source
1175
	 *
1176
	 * @return WP_Error
1177
	 */
1178
	static function check_for_main_files( $source, $remote_source ) {
1179
		if ( $source === $remote_source . '/jetpack-dev/' ) {
1180
			if ( ! file_exists( $source . 'jetpack.php' ) ) {
1181
				return new WP_Error( 'plugin_file_does_not_exist', __( 'Main Plugin File does not exist', 'jetpack-beta' ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'plugin_file_does_not_exist'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1182
			}
1183
			if ( ! file_exists( $source . '_inc/build/static.html' ) ) {
1184
				return new WP_Error( 'static_admin_page_does_not_exist', __( 'Static Admin Page File does not exist', 'jetpack-beta' ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'static_admin_page_does_not_exist'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1185
			}
1186
			if ( ! file_exists( $source . '_inc/build/admin.js' ) ) {
1187
				return new WP_Error( 'admin_page_does_not_exist', __( 'Admin Page File does not exist', 'jetpack-beta' ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'admin_page_does_not_exist'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1188
			}
1189
			// It has happened that sometimes a generated bundle from the master branch ends up with an empty
1190
			// vendor directory. Used to be a problem in the beta building process.
1191
			if ( self::is_dir_empty( $source . 'vendor' ) ) {
1192
				return new WP_Error( 'vendor_dir_is_empty', __( 'The dependencies dir (vendor) is empty', 'jetpack-beta' ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'vendor_dir_is_empty'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
1193
			}
1194
		}
1195
1196
		return $source;
1197
	}
1198
1199
	/**
1200
	 * Checks if a dir is empty
1201
	 *
1202
	 * @param [type] $dir The absolute directory path to check
0 ignored issues
show
Documentation introduced by
The doc-type [type] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
1203
	 * @return boolean
1204
	 */
1205
	static function is_dir_empty( $dir ) {
1206
		return ( count( scandir( $dir ) ) == 2 );
1207
	}
1208
1209
	/**
1210
	 * Callback function to include Jetpack beta options into Jetpack sync whitelist
1211
	 *
1212
	 * @param Array $whitelist List of whitelisted options to sync
1213
	 */
1214
	public function add_to_options_whitelist( $whitelist ) {
1215
		$whitelist[] = self::$option;
1216
		$whitelist[] = self::$option_dev_installed;
1217
		$whitelist[] = self::$option_autoupdate;
1218
		$whitelist[] = self::$option_email_notif;
1219
		return $whitelist;
1220
	}
1221
1222
	/**
1223
	 * Custom error handler to intercept errors and log them using Jetpack's own logger.
1224
	 *
1225
	 * @param int    $errno error code.
1226
	 * @param string $errstr error message.
1227
	 * @param string $errfile file name where the error happened.
1228
	 * @param int    $errline line in the code.
1229
	 *
1230
	 * @return bool whether to make the default handler handle the error as well.
1231
	 */
1232
	public static function custom_error_handler( $errno, $errstr, $errfile, $errline ) {
1233
1234
		if ( class_exists( 'Jetpack' ) && method_exists( 'Jetpack', 'log' ) ) {
1235
			$error_string = sprintf( '%s, %s:%d', $errstr, $errfile, $errline );
1236
1237
			// Only adding to log if the message is related to Jetpack.
1238
			if ( false !== stripos( $error_string, 'jetpack' ) ) {
1239
				Jetpack::log( $errno, $error_string );
1240
			}
1241
		}
1242
1243
		/**
1244
		 * The error_reporting call returns current error reporting level as an integer. Bitwise
1245
		 * AND lets us determine whether the current error is included in the current error
1246
		 * reporting level
1247
		 */
1248
		if ( ! ( error_reporting() & $errno ) ) {
1249
1250
			// If this error is not being reported in the current settings, stop reporting here by returning true.
1251
			return true;
1252
		}
1253
1254
		// Returning false makes the error go through the standard error handler as well.
1255
		return false;
1256
	}
1257
}
1258