Completed
Push — add/beta-plugin ( d1204d )
by
unknown
189:46 queued 179:34
created

Jetpack_Beta::get_branch_and_section_dev()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 3
nop 0
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
1
<?php
2
/**
3
 * Plugin Name: Jetpack Beta Tester
4
 * Plugin URI: https://jetpack.com/beta/
5
 * Description: Use the Beta plugin to get a sneak peek at new features and test them on your site.
6
 * Version: 2.4.4
7
 * Author: Automattic
8
 * Author URI: https://jetpack.com/
9
 * License: GPLv2 or later
10
 *
11
 * @package Jetpack Beta
12
 */
13
14
/*
15
This program is free software; you can redistribute it and/or
16
modify it under the terms of the GNU General Public License
17
as published by the Free Software Foundation; either version 2
18
of the License, or (at your option) any later version.
19
20
This program is distributed in the hope that it will be useful,
21
but WITHOUT ANY WARRANTY; without even the implied warranty of
22
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
GNU General Public License for more details.
24
25
You should have received a copy of the GNU General Public License
26
along with this program; if not, write to the Free Software
27
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
28
*/
29
30
if ( ! defined( 'ABSPATH' ) ) {
31
	exit;
32
}
33
34
/**
35
 * How this plugin works.
36
 * Jetpack beta manages files inside jetpack-dev folder this folder should contain
37
 */
38
define( 'JPBETA__PLUGIN_FOLDER',  basename( dirname( __FILE__ ) ) );
39
define( 'JPBETA__PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
40
define( 'JPBETA__PLUGIN_FILE', __FILE__ );
41
define( 'JPBETA_VERSION', '2.4.4' );
42
43
define( 'JPBETA_DEFAULT_BRANCH', 'rc_only' );
44
45
define( 'JETPACK_BETA_MANIFEST_URL', 'https://betadownload.jetpack.me/jetpack-branches.json' );
46
define( 'JETPACK_ORG_API_URL', 'https://api.wordpress.org/plugins/info/1.0/jetpack.json' );
47
define( 'JETPACK_GITHUB_API_URL', 'https://api.github.com/repos/Automattic/Jetpack/' );
48
define( 'JETPACK_GITHUB_URL', 'https://github.com/Automattic/jetpack' );
49
define( 'JETPACK_DEFAULT_URL', 'https://jetpack.com' );
50
51
define( 'JETPACK_DEV_PLUGIN_SLUG', 'jetpack-dev' );
52
53
define( 'JETPACK_PLUGIN_FILE', 'jetpack/jetpack.php' );
54
define( 'JETPACK_DEV_PLUGIN_FILE', 'jetpack-dev/jetpack.php' );
55
56
define( 'JETPACK_BETA_REPORT_URL', 'https://jetpack.com/contact-support/beta-group/' );
57
58
defined( 'JETPACK_GREEN' ) || define( 'JETPACK_GREEN', '#2fb41f' );
59
60
61
require_once 'autoupdate-self.php';
62
require_once 'class-jetpackbetaclicommand.php';
63
add_action( 'init', array( 'Jetpack_Beta_Autoupdate_Self', 'instance' ) );
64
65
set_error_handler( array( 'Jetpack_Beta', 'custom_error_handler' ) );
66
67
class Jetpack_Beta {
68
69
	protected static $_instance = null;
70
71
	static $option               = 'jetpack_beta_active';
72
	static $option_dev_installed = 'jetpack_beta_dev_currently_installed';
73
	static $option_autoupdate    = 'jp_beta_autoupdate';
74
	static $option_email_notif   = 'jp_beta_email_notifications';
75
76
	static $auto_update_cron_hook = 'jetpack_beta_autoupdate_hourly_cron';
77
78
	/**
79
	 * Main Instance
80
	 */
81
	public static function instance() {
82
		return self::$_instance = is_null( self::$_instance ) ? new self() : self::$_instance;
83
	}
84
85
	/**
86
	 * Constructor
87
	 */
88
	public function __construct() {
89
		if ( isset( $_GET['delete'] ) ) {
90
			delete_site_transient( 'update_plugins' );
91
		}
92
93
		add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'maybe_plugins_update_transient' ) );
94
		add_filter( 'upgrader_post_install', array( $this, 'upgrader_post_install' ), 10, 3 );
95
96
		add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ) );
97
		add_action( 'deactivate_plugin', array( $this, 'plugin_deactivated' ) , 10, 2 );
98
99
		add_action( 'upgrader_process_complete', array( $this, 'upgrader_process_complete' ), 10, 2 );
100
101
		add_filter( 'plugin_action_links_' . JETPACK_PLUGIN_FILE, array( $this, 'remove_activate_stable' ) );
102
		add_filter( 'plugin_action_links_' . JETPACK_DEV_PLUGIN_FILE, array( $this, 'remove_activate_dev' ) );
103
104
		add_filter( 'network_admin_plugin_action_links_' . JETPACK_PLUGIN_FILE, array( $this, 'remove_activate_stable' ) );
105
		add_filter( 'network_admin_plugin_action_links_' . JETPACK_DEV_PLUGIN_FILE, array( $this, 'remove_activate_dev' ) );
106
107
		add_filter( 'all_plugins', array( $this, 'update_all_plugins' ) );
108
109
		add_filter( 'plugins_api', array( $this, 'get_plugin_info' ), 10, 3 );
110
111
		add_action( 'jetpack_beta_autoupdate_hourly_cron', array( 'Jetpack_Beta', 'run_autoupdate' ) );
112
113
		add_filter( 'jetpack_options_whitelist', array( $this, 'add_to_options_whitelist' ) );
114
115
		if ( is_admin() ) {
116
			require JPBETA__PLUGIN_DIR . 'jetpack-beta-admin.php';
117
			Jetpack_Beta::maybe_schedule_autoupdate();
118
			Jetpack_Beta_Admin::init();
119
		}
120
	}
121
122
	public function upgrader_process_complete( $upgrader, $updates_completed ) {
123
		if ( ! isset( $updates_completed['plugins'] ) ) {
124
			return;
125
		}
126
127
		if ( $updates_completed['action'] == 'update' &&
128
		     $updates_completed['type'] == 'plugin' &&
129
		     in_array( JETPACK_DEV_PLUGIN_FILE, $updates_completed['plugins'] ) ) {
130
			list( $branch, $section ) = self::get_branch_and_section_dev();
131
			if ( self::should_update_dev_to_master() ) {
132
				list( $branch, $section ) = array( 'master', 'master' );
133
			}
134
			update_option( self::$option_dev_installed, array( $branch, $section, self::get_manifest_data( $branch, $section ) ) );
135
		}
136
137
	}
138
139
	public static function is_network_enabled() {
140
		if ( Jetpack_Beta::is_network_active() ) {
141
			add_filter( 'option_active_plugins', array( 'Jetpack_Beta','override_active_plugins' ) );
142
		}
143
	}
144
145
	/**
146
	 * @param $active_plugins
147
	 * Make sure that you can't have Jetpack and Jetpack Dev plugins versions loaded
148
	 * This filter is only applied if Jetpack is network activated.
149
	 * @return array
150
	 */
151
	public static function override_active_plugins( $active_plugins ) {
152
		$new_active_plugins = array();
153
		foreach( $active_plugins as $active_plugin ) {
154
			if ( ! self::is_jetpack_plugin( $active_plugin ) ) {
155
			$new_active_plugins[] = $active_plugin;
156
			}
157
		}
158
		return $new_active_plugins;
159
	}
160
161
	public function plugin_deactivated( $plugin, $network_wide ) {
162
		if ( ! Jetpack_Beta::is_jetpack_plugin( $plugin ) ) {
163
			return;
164
		}
165
166
		delete_option( Jetpack_Beta::$option );
167
	}
168
169
	public static function is_jetpack_plugin( $plugin ) {
170
		return in_array( $plugin, array( JETPACK_PLUGIN_FILE, JETPACK_DEV_PLUGIN_FILE ) );
171
	}
172
173
	public function remove_activate_dev( $actions ) {
174 View Code Duplication
		if ( is_plugin_active( JETPACK_PLUGIN_FILE ) || self::is_network_active() ) {
175
			$actions['activate'] = __( 'Plugin Already Active', 'jetpack-beta' );
176
		}
177
		return $actions;
178
	}
179
180
	public function remove_activate_stable( $actions ) {
181 View Code Duplication
		if ( is_plugin_active( JETPACK_DEV_PLUGIN_FILE ) || self::is_network_active() ) {
182
			$actions['activate'] = __( 'Plugin Already Active', 'jetpack-beta' );
183
		}
184
		return $actions;
185
	}
186
187
	public function update_all_plugins( $plugins ) {
188
		// WP.com requests away show regular plugin
189
		if ( defined( 'REST_API_REQUEST' ) && REST_API_REQUEST ) {
190
			//Ensure that Jetpack reports the version it's using on account of the Jetpack Beta plugin to Calypso
191
			if ( is_plugin_active( JETPACK_DEV_PLUGIN_FILE ) ) {
192
				$plugins[ JETPACK_PLUGIN_FILE ]['Version'] = $plugins[ JETPACK_DEV_PLUGIN_FILE ]['Version'];
193
			}
194
			unset( $plugins[ JETPACK_DEV_PLUGIN_FILE ] );
195
			return $plugins;
196
		}
197
198
		if ( is_plugin_active( JETPACK_DEV_PLUGIN_FILE ) ) {
199
			unset( $plugins[ JETPACK_PLUGIN_FILE ] );
200
		} else {
201
			unset( $plugins[ JETPACK_DEV_PLUGIN_FILE ] );
202
		}
203
		return $plugins;
204
	}
205
206
	public function update_jetpack_dev( $plugin ) {
207
		$plugin['Name'] = $plugin['Name'] . ' | ' . Jetpack_Beta::get_jetpack_plugin_pretty_version( true );
208
		return $plugin;
209
	}
210
211
	public function get_plugin_info( $false, $action, $response ) {
212
213
		// Check if this call API is for the right plugin
214
		if ( ! isset( $response->slug ) || $response->slug != JETPACK_DEV_PLUGIN_SLUG ) {
215
			return false;
216
		}
217
		$update_date =  null;
218
		$download_zip = null;
219
		$dev_data = self::get_dev_installed();
220
		if ( isset( $dev_data[2] ) ) {
221
			$update_date = $dev_data[2]->update_date;
222
			$download_zip = $dev_data[2]->download_url;
223
		}
224
		// Update tags
225
		$response->slug          = JETPACK_DEV_PLUGIN_SLUG;
226
		$response->plugin        = JETPACK_DEV_PLUGIN_SLUG;
227
		$response->name          = 'Jetpack | '. self::get_jetpack_plugin_pretty_version( true );
228
		$response->plugin_name   = 'Jetpack | '. self::get_jetpack_plugin_pretty_version( true );
229
		$response->version       = self::get_jetpack_plugin_version( true );
230
		$response->author        = 'Automattic';
231
		$response->homepage      = 'https://jetpack.com/contact-support/beta-group/';
232
		$response->downloaded    = false;
233
		$response->last_updated  = $update_date;
234
		$response->sections      = array( 'description' => Jetpack_Beta_Admin::to_test_content());
235
 		$response->download_link = $download_zip;
236
		return $response;
237
238
239
	}
240
	/**
241
	 * Run on activation to flush update cache
242
	 */
243
	public static function activate() {
244
		// don't do anyting funnly
245
		if ( defined('DOING_CRON')  ) {
246
			return;
247
		}
248
		delete_site_transient( 'update_plugins' );
249
	}
250
251
	public static function get_plugin_file() {
252
		return self::get_plugin_slug() . '/jetpack.php';
253
	}
254
255
	public static function get_plugin_slug() {
256
		$installed = self::get_branch_and_section();
257
		if ( empty( $installed ) || $installed[1] === 'stable' || $installed[1] === 'tags' ) {
258
			return 'jetpack';
259
		}
260
		return JETPACK_DEV_PLUGIN_SLUG;
261
	}
262
263
	public static function deactivate() {
264
		// don't do anyting funnly
265
		if ( defined('DOING_CRON')  ) {
266
			return;
267
		}
268
269
		Jetpack_Beta::clear_autoupdate_cron();
270
		Jetpack_Beta::delete_all_transiants();
271
		add_action( 'shutdown', array( __CLASS__, 'switch_active' ), 5 );
272
		add_action( 'shutdown', array( __CLASS__, 'remove_dev_plugin' ), 20 );
273
		delete_option( self::$option );
274
	}
275
276
	static function remove_dev_plugin() {
277
		if ( is_multisite() ) {
278
			return;
279
		}
280
281
		// Delete the jetpack dev plugin
282
		require_once ABSPATH . 'wp-admin/includes/file.php';
283
		$creds = request_filesystem_credentials( site_url() . '/wp-admin/', '', false, false, array() );
284
		if ( ! WP_Filesystem( $creds ) ) {
285
			/* any problems and we exit */
286
			return;
287
		}
288
		global $wp_filesystem;
289
		if ( ! $wp_filesystem ) {
290
			return;
291
		}
292
293
		$working_dir = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . JETPACK_DEV_PLUGIN_SLUG;
294
		// delete the folder JETPACK_BETA_PLUGIN_FOLDER
295
		if ( $wp_filesystem->is_dir( $working_dir ) ) {
296
			$wp_filesystem->delete( $working_dir, true );
297
		}
298
		// Since we are removing this dev plugin we should also clean up this data.
299
		delete_option( self::$option_dev_installed );
300
	}
301
302
	static function admin_url( $query = '?page=jetpack-beta' ) {
303
		return ( Jetpack_Beta::is_network_active() )
304
			? network_admin_url( 'admin.php' . $query )
305
			: admin_url( 'admin.php' . $query );
306
	}
307
308
	public function admin_bar_menu() {
309
		global $wp_admin_bar;
310
311
		if ( ! is_object( $wp_admin_bar ) )
312
			return;
313
314
		// Nothing got activated yet.
315
		if ( ! self::get_option() ) {
316
			return;
317
		}
318
319
		$args = array(
320
			'id'    => 'jetpack-beta_admin_bar',
321
			'title' => 'Jetpack Beta',
322
			'parent' => 'top-secondary',
323
			'href'  => current_user_can( 'update_plugins' ) ? self::admin_url() : ''
324
		);
325
		$wp_admin_bar->add_node( $args );
326
327
		// add a child item to our parent item
328
		$args = array(
329
			'id'     => 'jetpack-beta_version',
330
			'title'  => sprintf( __( 'Running %s', 'jetpack-beta' ), self::get_jetpack_plugin_pretty_version() ),
331
			'parent' => 'jetpack-beta_admin_bar'
332
		);
333
334
		$wp_admin_bar->add_node( $args );
335
336
		if ( self::get_plugin_slug() === JETPACK_DEV_PLUGIN_SLUG ) {
337
			// Highlight the menu if you are running the BETA Versions..
338
			echo sprintf( "<style>#wpadminbar #wp-admin-bar-jetpack-beta_admin_bar { background: %s; }</style>", JETPACK_GREEN );
339
		}
340
341
		$args = array(
342
			'id'     => 'jetpack-beta_report',
343
			'title'  => __( 'Report Bug', 'jetpack-beta' ),
344
			'href'   => JETPACK_BETA_REPORT_URL,
345
			'parent' => 'jetpack-beta_admin_bar'
346
		);
347
		$wp_admin_bar->add_node( $args );
348
349
		list( $branch, $section ) = self::get_branch_and_section();
350
		if( 'pr' === $section ) {
351
			$args = array(
352
				'id'     => 'jetpack-beta_report_more_info',
353
				'title'  => __( 'More Info ', 'jetpack-beta' ),
354
				'href'   => self::get_url( $branch, $section),
355
				'parent' => 'jetpack-beta_admin_bar'
356
			);
357
			$wp_admin_bar->add_node( $args );
358
		}
359
	}
360
361
	public function maybe_plugins_update_transient( $transient ) {
362
		if ( !isset( $transient->no_update ) ) {
363
			return $transient;
364
		}
365
366
		// Do not try to update things that do not exist
367
		if ( ! file_exists(  WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . JETPACK_DEV_PLUGIN_FILE ) ) {
368
			return $transient;
369
		}
370
371
		// Do not look for update if we are stable branch
372
		if ( self::is_on_stable() ) {
373
			return $transient;
374
		}
375
376
		// Lets always grab the latest
377
		delete_site_transient( 'jetpack_beta_manifest' );
378
379
		// check if there is a new version
380
		if ( self::should_update_dev_to_master() ) {
381
			// If response is false, don't alter the transient
382
			$transient->response[ JETPACK_DEV_PLUGIN_FILE ] = self::get_jepack_dev_master_update_response();
383
			// unset the that it doesn't need an update...
384
			unset( $transient->no_update[ JETPACK_DEV_PLUGIN_FILE ] );
385
		} else if( self::should_update_dev_version() ) {
386
			// If response is false, don't alter the transient
387
			$transient->response[ JETPACK_DEV_PLUGIN_FILE ] = self::get_jepack_dev_update_response();
388
			// unset the that it doesn't need an update...
389
			unset( $transient->no_update[ JETPACK_DEV_PLUGIN_FILE ] );
390
		} else {
391
			unset( $transient->response[ JETPACK_DEV_PLUGIN_FILE ] );
392
			if ( isset( $transient->no_update ) ) {
393
				$transient->no_update[ JETPACK_DEV_PLUGIN_FILE ] = self::get_jepack_dev_update_response();
394
			}
395
		}
396
397
		return $transient;
398
	}
399
400
	static function should_update_dev_version() {
401
		return version_compare( self::get_new_jetpack_version( true ), self::get_jetpack_plugin_version( true ), '>' );
402
	}
403
404
	static function get_jepack_dev_update_response() {
405
		$response               = new stdClass;
406
		$response->id           = JETPACK_DEV_PLUGIN_SLUG;
407
		$response->plugin       = JETPACK_DEV_PLUGIN_SLUG;
408
		$response->new_version  = self::get_new_jetpack_version( true );
409
		$response->slug         = JETPACK_DEV_PLUGIN_SLUG;
410
		$response->url          = self::get_url_dev();
411
		$response->package      = self::get_install_url_dev();
412
		return $response;
413
	}
414
415
	static function get_jepack_dev_master_update_response() {
416
		$response = self::get_jepack_dev_update_response();
417
418
		$master_manifest = self::get_manifest_data( 'master', 'master' );
419
		$response->new_version  = $master_manifest->version;
420
		$response->url          = self::get_url( 'master', 'master' );
421
		$response->package      = $master_manifest->download_url;
422
		return $response;
423
	}
424
425
	/**
426
	 * Moves the newly downloaded folder into jetpack-dev
427
	 * @param $worked
428
	 * @param $hook_extras
429
	 * @param $result
430
	 *
431
	 * @return WP_Error
432
	 */
433
	public function upgrader_post_install( $worked, $hook_extras, $result ) {
434
		global $wp_filesystem;
435
436
		if (
437
			! isset( $hook_extras['plugin'] )
438
			|| JETPACK_DEV_PLUGIN_FILE !== $hook_extras['plugin']
439
		) {
440
			return $worked;
441
		}
442
443
		if ( $wp_filesystem->move( $result['destination'], WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . JETPACK_DEV_PLUGIN_SLUG , true ) ) {
444
			return $worked;
445
		} else {
446
			return new WP_Error();
447
		}
448
	}
449
450
	static function get_jetpack_plugin_version( $is_dev_version = false ) {
451
		if ( $is_dev_version ) {
452
			$info = self::get_jetpack_plugin_info_dev();
453
		} else {
454
			$info = self::get_jetpack_plugin_info();
455
		}
456
457
		return isset( $info['Version'] ) ? $info['Version'] : 0 ;
458
	}
459
460
	static function get_option() {
461
		return get_option( self::$option );
462
	}
463
464
	static function get_dev_installed() {
465
		return get_option( self::$option_dev_installed );
466
	}
467
468
	static function get_branch_and_section() {
469
		$option = (array) self::get_option();
470
		if ( false === $option[0] ) {
471
			// see if the jetpack is plugin enabled
472
			if ( is_plugin_active( JETPACK_PLUGIN_FILE ) ) {
473
				return array( 'stable', 'stable' );
474
			}
475
			return array( false, false );
476
		}
477
		// branch and section
478
		return $option;
479
	}
480
481
	static function is_on_stable() {
482
		$branch_and_section = self::get_branch_and_section();
483
		if ( empty( $branch_and_section[0] ) || $branch_and_section[0] == 'stable' ) {
484
			return true;
485
		}
486
		return false;
487
	}
488
489
	static function is_on_tag() {
490
		$option = (array) self::get_option();
491
		if ( isset( $option[1] ) && 'tags' === $option[1] ) {
492
			return true;
493
		}
494
		return false;
495
	}
496
497
	static function get_branch_and_section_dev() {
498
		$option = (array) self::get_dev_installed();
499
		if ( false !== $option[0] && isset( $option[1] )) {
500
			return array( $option[0], $option[1] );
501
		}
502
		if ( is_plugin_active( JETPACK_DEV_PLUGIN_FILE ) ) {
503
			return array( 'stable', 'stable' );
504
		}
505
		return array( false, false );
506
	}
507
508
	static function get_jetpack_plugin_pretty_version( $is_dev_version = false ) {
509
		if( $is_dev_version ) {
510
			list( $branch, $section ) = self::get_branch_and_section_dev();
511
		} else {
512
			list( $branch, $section ) = self::get_branch_and_section();
513
		}
514
515
		if ( ! $section  ) {
516
			return '';
517
		}
518
519
		if ( 'master' === $section ) {
520
			return 'Bleeding Edge';
521
		}
522
523
		if ( 'stable' === $section ) {
524
			return 'Latest Stable';
525
		}
526
527
		if ( 'tags' === $section ) {
528
			return sprintf(
529
				__( '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' ),
530
				esc_attr( $branch )
531
			);
532
		}
533
534
		if ( 'rc' === $section ) {
535
			return 'Release Candidate';
536
		}
537
538
		if ( 'pr' === $section ) {
539
			$branch = str_replace( '-', ' ', $branch );
540
			return 'Feature Branch: ' . str_replace( '_', ' / ', $branch );
541
		}
542
543
		return self::get_jetpack_plugin_version();
544
	}
545
546
	static function get_new_jetpack_version( $is_dev_version = false ) {
547
		$manifest = self::get_beta_manifest();
548
		if ( $is_dev_version ) {
549
			list( $branch, $section ) = self::get_branch_and_section_dev();
550
		} else {
551
			list( $branch, $section ) = self::get_branch_and_section();
552
		}
553
554
		if ( 'master' === $section && isset( $manifest->{$section}->version ) ) {
555
			return $manifest->{$section}->version;
556
		}
557
558
		if ( 'rc' === $section && isset( $manifest->{$section}->version ) ) {
559
			return $manifest->{$section}->version;
560
		}
561
562
		if ( isset( $manifest->{$section} ) &&
563
		     isset( $manifest->{$section}->{$branch} ) &&
564
		     isset( $manifest->{$section}->{$branch}->version )
565
		   ) {
566
			return $manifest->{$section}->{$branch}->version;
567
		}
568
		return 0;
569
	}
570
571
	static function get_url_dev() {
572
		list( $branch, $section ) = self::get_branch_and_section_dev();
573
		return self::get_url( $branch, $section );
574
	}
575
576
	static function get_url( $branch = null, $section = null ) {
577
		if ( is_null ( $section ) ) {
578
			list( $branch, $section ) = self::get_branch_and_section();
579
		}
580
581
		if ( 'master' === $section ) {
582
			return JETPACK_GITHUB_URL . '/tree/master-build';
583
		}
584
585
		if ( 'rc' === $section ) {
586
			return JETPACK_GITHUB_URL . '/tree/' . $section . '-build';
587
		}
588
589
		if ( 'pr' === $section ) {
590
			$manifest = self::get_beta_manifest();
591
			return isset( $manifest->{$section}->{$branch}->pr )
592
				? JETPACK_GITHUB_URL  . '/pull/' . $manifest->{$section}->{$branch}->pr
593
				: JETPACK_DEFAULT_URL;
594
		}
595
		return JETPACK_DEFAULT_URL;
596
	}
597
598
	static function get_install_url_dev() {
599
		list( $branch, $section ) = self::get_branch_and_section_dev();
600
		return self::get_install_url( $branch, $section );
601
	}
602
603
	static function get_install_url( $branch = null, $section = null ) {
604
		if ( is_null( $section ) ) {
605
			list( $branch, $section ) = self::get_branch_and_section();
606
		}
607
608
		if ( 'stable' === $section ) {
609
			$org_data = self::get_org_data();
610
			return $org_data->download_link;
611
		} else if ( 'tags' === $section ) {
612
			$org_data = self::get_org_data();
613
			return $org_data->versions->{$branch} ?: false;
614
		}
615
		$manifest = Jetpack_Beta::get_beta_manifest( true );
616
617
		if ( 'master' === $section && isset( $manifest->{$section}->download_url ) ) {
618
			return $manifest->{$section}->download_url;
619
		}
620
621
		if ( 'rc' === $section ) {
622
			if ( isset( $manifest->{$section}->download_url ) ) {
623
				return $manifest->{$section}->download_url;
624
			}
625
			$branches = array_keys( (array) $manifest->{$section} );
626
			foreach ( $branches as $branch ) {
627
				if ( isset( $manifest->{$section}->{$branch}->download_url ) ) {
628
					return $manifest->{$section}->{$branch}->download_url;
629
				}
630
			}
631
			return null;
632
		}
633
634
		if ( isset( $manifest->{$section}->{$branch}->download_url ) ) {
635
			return $manifest->{$section}->{$branch}->download_url;
636
		}
637
		return null;
638
	}
639
640
	static function get_jetpack_plugin_info_stable() {
641
		return self::get_jetpack_plugin_info( JETPACK_PLUGIN_FILE );
642
	}
643
644
	static function get_jetpack_plugin_info_dev() {
645
		return self::get_jetpack_plugin_info( JETPACK_DEV_PLUGIN_FILE );
646
	}
647
648
	static function get_jetpack_plugin_info( $plugin_file = null ) {
649
650
		if ( is_null( $plugin_file ) ) {
651
			$plugin_file = self::get_plugin_file();
652
		}
653
654
		if( ! function_exists( 'get_plugin_data' ) ) {
655
			require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
656
		}
657
		$plugin_file_path = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $plugin_file;
658
659
		if ( file_exists( $plugin_file_path ) ) {
660
			return get_plugin_data( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $plugin_file );
661
		}
662
663
		return null;
664
	}
665
666
	/*
667
	 * This needs to happen on shutdown. Other wise it doesn't work.
668
	 */
669
	static function switch_active() {
670
		self::replace_active_plugin( JETPACK_DEV_PLUGIN_FILE, JETPACK_PLUGIN_FILE );
671
	}
672
673
	static function get_beta_manifest( $force_refresh = false ) {
674
		return self::get_remote_data( JETPACK_BETA_MANIFEST_URL, 'manifest', $force_refresh );
675
	}
676
677
	static function get_org_data() {
678
		return self::get_remote_data( JETPACK_ORG_API_URL, 'org_data' );
679
	}
680
681
	static function get_remote_data( $url, $transient, $bypass = false) {
682
		$prefix = 'jetpack_beta_';
683
		$cache  = get_site_transient( $prefix . $transient );
684
		if ( $cache && ! $bypass ) {
685
			return $cache;
686
		}
687
688
		$remote_manifest = wp_remote_get( $url );
689
690
		if ( is_wp_error( $remote_manifest ) ) {
691
			return false;
692
		}
693
694
		$cache = json_decode( wp_remote_retrieve_body( $remote_manifest ) );
695
		set_site_transient( $prefix . $transient, $cache, MINUTE_IN_SECONDS * 15 );
696
697
		return $cache;
698
	}
699
700
	static function delete_all_transiants() {
701
		$prefix = 'jetpack_beta_';
702
703
		delete_site_transient( $prefix. 'org_data' );
704
		delete_site_transient( $prefix. 'manifest' );
705
706
		delete_site_transient( Jetpack_Beta_Autoupdate_Self::TRANSIENT_NAME );
707
708
	}
709
710
	static function install_and_activate( $branch, $section ) {
711
712
		// Clean up previous version of the beta plugin
713
		if ( file_exists( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . 'jetpack-pressable-beta' ) ) {
714
			// Delete the jetpack dev plugin
715
			require_once ABSPATH . 'wp-admin/includes/file.php';
716
			$creds = request_filesystem_credentials( site_url() . '/wp-admin/', '', false, false, array() );
717
			if ( ! WP_Filesystem( $creds ) ) {
718
				/* any problems and we exit */
719
				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...
720
			}
721
			global $wp_filesystem;
722
			if ( ! $wp_filesystem ) {
723
				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...
724
			}
725
726
			$working_dir = WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . 'jetpack-pressable-beta';
727
			// delete the folder JETPACK_BETA_PLUGIN_FOLDER
728
			if ( $wp_filesystem->is_dir( $working_dir ) ) {
729
				$wp_filesystem->delete( $working_dir, true );
730
			}
731
			// Deactivate the plugin
732
			self::replace_active_plugin( 'jetpack-pressable-beta/jetpack.php' );
733
		}
734
735 View Code Duplication
		if ( 'stable' === $section &&
736
		     file_exists( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . JETPACK_PLUGIN_FILE ) ) {
737
			self::replace_active_plugin( JETPACK_DEV_PLUGIN_FILE, JETPACK_PLUGIN_FILE, true );
738
			self::update_option( $branch, $section );
739
			return;
740
		}
741
742 View Code Duplication
		if ( self::get_branch_and_section_dev() === array( $branch, $section )
743
		     && file_exists( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . JETPACK_DEV_PLUGIN_FILE ) ) {
744
			self::replace_active_plugin( JETPACK_PLUGIN_FILE, JETPACK_DEV_PLUGIN_FILE, true );
745
			self::update_option( $branch, $section );
746
			return;
747
		}
748
749
		self::proceed_to_install_and_activate(
750
			self::get_install_url( $branch, $section ),
751
			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...
752
			$section
753
		);
754
		self::update_option( $branch, $section );
755
		return;
756
	}
757
758
	static function update_plugin( $branch, $section ) {
759
		self::proceed_to_install(
760
			self::get_install_url( $branch, $section ),
761
			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...
762
			$section
763
		);
764
765 View Code Duplication
		if ( $section !== 'stable' ) {
766
			update_option( self::$option_dev_installed, array( $branch, $section, self::get_manifest_data( $branch, $section ) ) );
767
		}
768
		return;
769
	}
770
771
	static function update_option( $branch, $section ) {
772 View Code Duplication
		if ( 'stable' !== $section ) {
773
			update_option( self::$option_dev_installed, array( $branch, $section, self::get_manifest_data( $branch, $section ) ) );
774
		}
775
		update_option( self::$option, array( $branch, $section) );
776
	}
777
778
	static function get_manifest_data( $branch, $section ) {
779
		$installed = get_option( self::$option_dev_installed );
780
		$current_manifest_data = isset( $installed[2] ) ? $installed[2] : false;
781
782
		$manifest_data = self::get_beta_manifest();
783
784
		if ( ! isset( $manifest_data->{$section} ) ) {
785
			return $current_manifest_data;
786
		}
787
788
		if ( 'master' === $section ) {
789
			return $manifest_data->{$section};
790
		}
791
792
		if ( 'rc' === $section ) {
793
			return $manifest_data->{$section};
794
		}
795
796
		if ( isset( $manifest_data->{$section}->{$branch} ) ) {
797
			return $manifest_data->{$section}->{$branch};
798
		}
799
800
		return $current_manifest_data;
801
	}
802
803
	static function proceed_to_install_and_activate( $url, $plugin_folder = JETPACK_DEV_PLUGIN_SLUG, $section ) {
804
		self::proceed_to_install( $url, $plugin_folder, $section );
805
806
		if ( 'stable' === $section || 'tags' === $section ) {
807
			self::replace_active_plugin( JETPACK_DEV_PLUGIN_FILE, JETPACK_PLUGIN_FILE, true );
808
		} else {
809
			self::replace_active_plugin( JETPACK_PLUGIN_FILE, JETPACK_DEV_PLUGIN_FILE, true );
810
		}
811
	}
812
813
	static function proceed_to_install( $url, $plugin_folder = JETPACK_DEV_PLUGIN_SLUG, $section ) {
814
		$temp_path = download_url( $url );
815
816
		if ( is_wp_error( $temp_path ) ) {
817
			wp_die( sprintf( __( 'Error Downloading: <a href="%1$s">%1$s</a> - Error: %2$s', 'jetpack-beta' ), $url, $temp_path->get_error_message() ) );
818
		}
819
		require_once ABSPATH . 'wp-admin/includes/file.php';
820
		$creds = request_filesystem_credentials( site_url() . '/wp-admin/', '', false, false, array() );
821
		/* initialize the API */
822
		if ( ! WP_Filesystem( $creds ) ) {
823
			/* any problems and we exit */
824
			wp_die( __( 'Jetpack Beta: No File System access', 'jetpack-beta' ) );
825
		}
826
827
		global $wp_filesystem;
828
		if ( 'stable' === $section || 'tags' === $section ) {
829
			$plugin_path = WP_PLUGIN_DIR;
830
		} else {
831
			$plugin_path = str_replace( ABSPATH, $wp_filesystem->abspath(), WP_PLUGIN_DIR  );
832
		}
833
834
		$result = unzip_file( $temp_path, $plugin_path );
835
836
		if ( is_wp_error( $result ) ) {
837
			wp_die( sprintf( __( 'Error Unziping file: Error: %1$s', 'jetpack-beta' ), $result->get_error_message() ) );
838
		}
839
	}
840
841
	static function is_network_active() {
842
		if ( ! is_multisite() ) {
843
			return false;
844
		}
845
846
		if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
847
			return false;
848
		}
849
850
		if ( is_plugin_active_for_network( JETPACK_PLUGIN_FILE ) || is_plugin_active_for_network( JETPACK_DEV_PLUGIN_FILE ) ){
851
			return true;
852
		}
853
854
		return false;
855
	}
856
857
	static function replace_active_plugin( $current_plugin, $replace_with_plugin = null, $force_activate = false ) {
858
		if ( self::is_network_active() ) {
859
			$new_active_plugins = array();
860
			$network_active_plugins = get_site_option( 'active_sitewide_plugins' );
861
			foreach ( $network_active_plugins as $plugin => $date ) {
862
				$key = ( $plugin === $current_plugin ? $replace_with_plugin : $plugin );
863
				$new_active_plugins[ $key ] = $date;
864
			}
865
			update_site_option( 'active_sitewide_plugins', $new_active_plugins );
866
			return;
867
		}
868
869
		$active_plugins     = (array) get_option( 'active_plugins', array() );
870
		$new_active_plugins = array();
871
872
		if ( empty( $replace_with_plugin ) ) {
873
			$new_active_plugins = array_diff( $active_plugins, array( $current_plugin ) );
874
		} else {
875
			foreach ( $active_plugins as $plugin ) {
876
				$new_active_plugins[] = ( $plugin === $current_plugin ? $replace_with_plugin : $plugin );
877
			}
878
		}
879
880
		if ( $force_activate && ! in_array( $replace_with_plugin, $new_active_plugins ) ) {
881
			$new_active_plugins[] = $replace_with_plugin;
882
		}
883
		update_option( 'active_plugins', $new_active_plugins );
884
	}
885
886
	static function should_update_stable_version() {
887
		// Pressable Jetpack version is manage via Pressable
888
		if( defined( 'IS_PRESSABLE' ) && IS_PRESSABLE ) {
889
			return false;
890
		}
891
		// Check if we are Jetpack plugin is installed via git
892
		if ( file_exists ( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . 'jetpack/.git' ) ) {
893
			return false;
894
		}
895
896
		// Check if running a tag directly from svn
897
		if ( Jetpack_Beta::is_on_tag() ) {
898
			return false;
899
		}
900
901
		$updates = get_site_transient( 'update_plugins' );
902
903
		if ( isset( $updates->response, $updates->response[ JETPACK_PLUGIN_FILE ] ) ) {
904
			return true;
905
		}
906
		$org_data = self::get_org_data();
907
		$plugin_data = self::get_jetpack_plugin_info_stable();
908
909
		return ( isset( $plugin_data['Version'], $org_data->version )
910
		         && $org_data->version !== $plugin_data['Version'] );
911
	}
912
913
	/**
914
	 * Here we are checking if the DEV branch that we are currenly on is not something that is available in the manifest
915
	 * Meaning that the DEV branch was merged into master and so we need to update it.
916
	 * @return bool
917
	 */
918
	static function should_update_dev_to_master() {
919
		list( $branch, $section ) = self::get_branch_and_section_dev();
920
921
		if ( false === $branch || 'master' === $section || 'rc' === $section || 'tags' === $section ) {
922
			return false;
923
		}
924
		$manifest = self::get_beta_manifest();
925
		return ! isset( $manifest->{$section}->{$branch} );
926
	}
927
928
	static function is_set_to_autoupdate() {
929
		return get_option( 'jp_beta_autoupdate', false );
930
	}
931
932
	static function is_set_to_email_notifications() {
933
		return get_option( 'jp_beta_email_notifications', true );
934
	}
935
936
	static function clear_autoupdate_cron() {
937
		if ( ! is_main_site() ) {
938
			return;
939
		}
940
		wp_clear_scheduled_hook( Jetpack_Beta::$auto_update_cron_hook );
941
942
		if ( function_exists( 'wp_unschedule_hook' ) ) { // new in WP 4.9
943
			wp_unschedule_hook( Jetpack_Beta::$auto_update_cron_hook );
944
		}
945
	}
946
947
	static function schedule_hourly_autoupdate() {
948
		wp_clear_scheduled_hook(  Jetpack_Beta::$auto_update_cron_hook );
949
		wp_schedule_event( time(), 'hourly',  Jetpack_Beta::$auto_update_cron_hook );
950
	}
951
952
	static function maybe_schedule_autoupdate() {
953
		if ( ! Jetpack_Beta::is_set_to_autoupdate() ) {
954
			return;
955
		}
956
957
		if ( ! is_main_site() ) {
958
			return;
959
		}
960
		$has_schedule_already = wp_get_schedule( Jetpack_Beta::$auto_update_cron_hook );
961
		if ( ! $has_schedule_already ) {
962
			Jetpack_Beta::schedule_hourly_autoupdate();
963
		}
964
	}
965
966
	static function what_changed() {
967
		if ( $commit = Jetpack_Beta::get_version_commit() ) {
968
			$html = '';
969
			$commit_data = Jetpack_Beta::get_commit_data_from_github( $commit );
970
			if ( isset( $commit_data->commit->message ) ) {
971
				$html .= sprintf(
972
					__( "\n %s \n\n[Commit](%s)", 'jetpack-beta' ),
973
						esc_html( $commit_data->commit->message ),
974
						esc_url( $commit_data->html_url )
975
					);
976
				"\n\n";
977
			}
978
			if ( ! empty( $commit_data->files ) ) {
979
				$html .= "\n\n";
980
				$html .= sprintf( _n( 'One file changed ', '%d files changed',  count( $commit_data->files ), 'jetpack-beta' ), count( $commit_data->files ) );
981
				$html .= "\n";
982
				foreach(  $commit_data->files as $file ) {
983
					$added_deleted_changed = array();
984
					if( $file->additions ) {
985
						$added_deleted_changed[] = '+'. $file->additions;
986
					}
987
					if ( $file->deletions ) {
988
						$added_deleted_changed[] = '-'. $file->deletions;
989
					}
990
					$html .= sprintf( "- %s ... (%s %s) \n",  esc_html( $file->filename ), esc_html( $file->status ), implode( ' ', $added_deleted_changed ) );
991
				}
992
				$html .= "\n\n";
993
			}
994
			if ( ! empty( $html ) ) {
995
				return $html;
996
			}
997
		}
998
		return false;
999
	}
1000
1001
	static function get_version_commit() {
1002
		$split_version = explode( '-', Jetpack_Beta::get_jetpack_plugin_version() );
1003
		if ( isset( $split_version[3] )) {
1004
			return $split_version[3];
1005
		}
1006
		return false;
1007
	}
1008
1009
	static function get_commit_data_from_github( $commit ) {
1010
		return self::get_remote_data( JETPACK_GITHUB_API_URL.'commits/'.$commit, 'github_commits_' . $commit );
1011
	}
1012
1013
	static function run_autoupdate() {
1014
		if ( ! Jetpack_Beta::is_set_to_autoupdate() ) {
1015
			return;
1016
		}
1017
1018
		if ( ! is_main_site() ) {
1019
			return;
1020
		}
1021
1022
		require_once ABSPATH . 'wp-admin/includes/file.php';
1023
		require_once ABSPATH . 'wp-admin/includes/plugin.php';
1024
		require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
1025
		wp_clean_plugins_cache();
1026
		ob_start();
1027
		wp_update_plugins(); // Check for Plugin updates
1028
		ob_end_clean();
1029
		$plugins = array();
1030
		if (
1031
			! Jetpack_Beta::is_on_stable() &&
1032
			( Jetpack_Beta::should_update_dev_to_master() || Jetpack_Beta::should_update_dev_version() )
1033
		) {
1034
			add_filter( 'upgrader_source_selection', array( 'Jetpack_Beta', 'check_for_main_files' ), 10, 2 );
1035
1036
			// If response is false, don't alter the transient
1037
			$plugins[] = JETPACK_DEV_PLUGIN_FILE;
1038
		}
1039
		$autupdate = Jetpack_Beta_Autoupdate_Self::instance();
1040
		if ( $autupdate->has_never_version() ) {
1041
			$plugins[] = JPBETA__PLUGIN_FOLDER . '/jetpack-beta.php';
1042
		}
1043
1044
		if ( empty( $plugins ) ) {
1045
			return;
1046
		}
1047
1048
		// unhook this functions that output things before we send our response header.
1049
		remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
1050
		remove_action( 'upgrader_process_complete', 'wp_version_check' );
1051
		remove_action( 'upgrader_process_complete', 'wp_update_themes' );
1052
1053
		$skin = new WP_Ajax_Upgrader_Skin();
1054
		// The Automatic_Upgrader_Skin skin shouldn't output anything.
1055
		$upgrader = new Plugin_Upgrader( $skin );
1056
		$upgrader->init();
1057
		// This avoids the plugin to be deactivated.
1058
		// Using bulk upgrade puts the site into maintenance mode during the upgrades
1059
		$result             = $upgrader->bulk_upgrade( $plugins );
1060
		$errors             = $upgrader->skin->get_errors();
1061
		$log = $upgrader->skin->get_upgrade_messages();
1062
1063
		if ( is_wp_error( $errors ) && $errors->get_error_code() ) {
1064
			return $errors;
1065
		}
1066
1067
		if ( $result && ! defined( 'JETPACK_BETA_SKIP_EMAIL' ) && self::is_set_to_email_notifications() ) {
1068
			self::send_autoupdate_email( $plugins, $log );
1069
		}
1070
	}
1071
1072
	/**
1073
	 * Builds and sends an email about succesfull plugin autoupdate
1074
	 *
1075
	 * @param Array  $plugins List of plugins that were updated.
1076
	 * @param String $log upgrade message from core's plugin upgrader.
1077
	 */
1078
	private static function send_autoupdate_email( $plugins, $log ) {
1079
		$admin_email = get_site_option( 'admin_email' );
1080
1081
		if ( empty( $admin_email ) ) {
1082
			return;
1083
		}
1084
1085
		// In case the code is called in a scope different from wp-admin.
1086
		require_once JPBETA__PLUGIN_DIR . 'jetpack-beta-admin.php';
1087
1088
		// Calling empty() on a function return value crashes in PHP < 5.5.
1089
		// Thus we assign the return value explicitly and then check with empty().
1090
		$bloginfo_name = get_bloginfo( 'name' );
1091
		$site_title    = ! empty( $bloginfo_name ) ? get_bloginfo( 'name' ) : get_site_url();
1092
		$what_updated  = 'Jetpack Beta Tester Plugin';
1093
		$subject       = sprintf( __( '[%s] Autoupdated Jetpack Beta Tester', 'jetpack-beta' ), $site_title );
1094
1095
		if ( in_array( JETPACK_DEV_PLUGIN_FILE, $plugins, true ) ) {
1096
			$subject = sprintf(
1097
				__( '[%s] Autoupdated Jetpack %s ', 'jetpack-beta' ),
1098
				$site_title,
1099
				self::get_jetpack_plugin_pretty_version()
1100
			);
1101
1102
			$what_updated = sprintf(
1103
				__( 'Jetpack %s (%s)', 'jetpack-beta' ),
1104
				self::get_jetpack_plugin_pretty_version(),
1105
				self::get_jetpack_plugin_version()
1106
			);
1107
1108
			if ( count( $plugins ) > 1 ) {
1109
				$subject = sprintf(
1110
					__( '[%s] Autoupdated Jetpack %s and the Jetpack Beta Tester', 'jetpack-beta' ),
1111
					$site_title,
1112
					self::get_jetpack_plugin_pretty_version()
1113
				);
1114
1115
				$what_updated = sprintf(
1116
					__( 'Jetpack %s (%s) and the Jetpack Beta Tester', 'jetpack-beta' ),
1117
					self::get_jetpack_plugin_pretty_version(),
1118
					self::get_jetpack_plugin_version()
1119
				);
1120
			}
1121
		}
1122
1123
		$message  = sprintf(
1124
			__( 'Howdy! Your site at %1$s has autoupdated %2$s.', 'jetpack-beta' ),
1125
			home_url(),
1126
			$what_updated
1127
		);
1128
		$message .= "\n\n";
1129
1130
		$what_changed = self::what_changed();
1131
		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...
1132
			$message .= __( 'What changed?', 'jetpack-beta' );
1133
			$message .= wp_strip_all_tags( $what_changed );
1134
		}
1135
1136
		$message .= __( 'During the autoupdate the following happened:', 'jetpack-beta' );
1137
		$message .= "\n\n";
1138
		// Can only reference the About screen if their update was successful.
1139
		$log      = array_map( 'html_entity_decode', $log );
1140
		$message .= ' - ' . implode( "\n - ", $log );
1141
		$message .= "\n\n";
1142
1143
		// Adds To test section. for PR's it's a PR description, for master/RC - it's a to_test.md file contents.
1144
		$message .= Jetpack_Beta_Admin::to_test_content();
1145
		$message .= "\n\n";
1146
1147
		wp_mail( $admin_email, $subject, $message );
1148
	}
1149
1150
	/**
1151
	 * This checks intends to fix errors in our build server when jetpack
1152
	 * @param $source
1153
	 * @param $remote_source
1154
	 *
1155
	 * @return WP_Error
1156
	 */
1157
	static function check_for_main_files( $source, $remote_source ) {
1158
		if ( $source === $remote_source . '/jetpack-dev/' ) {
1159
			if ( ! file_exists( $source . 'jetpack.php' ) ) {
1160
				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...
1161
			}
1162
			if ( ! file_exists( $source . '_inc/build/static.html' ) ) {
1163
				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...
1164
			}
1165
			if ( ! file_exists( $source . '_inc/build/admin.js' ) ) {
1166
				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...
1167
			}
1168
			// It has happened that sometimes a generated bundle from the master branch ends up with an empty
1169
			// vendor directory. Used to be a problem in the beta building process.
1170
			if ( self::is_dir_empty( $source . 'vendor' ) ) {
1171
				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...
1172
			}
1173
		}
1174
1175
		return $source;
1176
	}
1177
1178
	/**
1179
	 * Checks if a dir is empty
1180
	 *
1181
	 * @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...
1182
	 * @return boolean
1183
	 */
1184
	static function is_dir_empty( $dir ) {
1185
		return ( count( scandir( $dir ) ) == 2 );
1186
	}
1187
1188
	/**
1189
	 * Callback function to include Jetpack beta options into Jetpack sync whitelist
1190
	 *
1191
	 * @param Array $whitelist List of whitelisted options to sync
1192
	 */
1193
	public function add_to_options_whitelist( $whitelist ) {
1194
		$whitelist[] = self::$option;
1195
		$whitelist[] = self::$option_dev_installed;
1196
		$whitelist[] = self::$option_autoupdate;
1197
		$whitelist[] = self::$option_email_notif;
1198
		return $whitelist;
1199
	}
1200
1201
	/**
1202
	 * Custom error handler to intercept errors and log them using Jetpack's own logger.
1203
	 *
1204
	 * @param int $errno error code.
1205
	 * @param string $errstr error message.
1206
	 * @param string $errfile file name where the error happened.
1207
	 * @param int $errline line in the code.
1208
	 *
1209
	 * @return bool whether to make the default handler handle the error as well.
1210
	 */
1211
	public static function custom_error_handler( $errno, $errstr, $errfile, $errline ) {
1212
1213
		if ( class_exists( 'Jetpack' ) && method_exists( 'Jetpack', 'log' ) ) {
1214
			$error_string = sprintf( "%s, %s:%d", $errstr, $errfile, $errline );
1215
1216
			// Only adding to log if the message is related to Jetpack.
1217
			if ( false !== stripos( $error_string, 'jetpack' ) ) {
1218
				Jetpack::log( $errno, $error_string );
1219
			}
1220
		}
1221
1222
		/**
1223
		 * The error_reporting call returns current error reporting level as an integer. Bitwise
1224
		 * AND lets us determine whether the current error is included in the current error
1225
		 * reporting level
1226
		 */
1227
		if ( ! ( error_reporting() & $errno ) ) {
1228
1229
			// If this error is not being reported in the current settings, stop reporting here by returning true.
1230
			return true;
1231
		}
1232
1233
		// Returning false makes the error go through the standard error handler as well.
1234
		return false;
1235
	}
1236
}
1237
1238
register_activation_hook( __FILE__, array( 'Jetpack_Beta', 'activate' ) );
1239
register_deactivation_hook( __FILE__, array( 'Jetpack_Beta', 'deactivate' ) );
1240
1241
add_action( 'init', array( 'Jetpack_Beta', 'instance' ) );
1242
add_action( 'muplugins_loaded', array( 'Jetpack_Beta', 'is_network_enabled' ) );
1243