Completed
Push — add/identity-crisis-package ( 78b820...24ac45 )
by
unknown
130:29 queued 119:17
created

Identity_Crisis::enqueue_idc_notice_files()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 2
nop 0
dl 0
loc 52
rs 9.0472
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Identity_Crisis package.
4
 *
5
 * @package  automattic/jetpack-identity-crisis
6
 */
7
8
namespace Automattic\Jetpack;
9
10
use Automattic\Jetpack\Assets\Logo as Jetpack_Logo;
11
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
12
use Automattic\Jetpack\Constants as Constants;
13
use Automattic\Jetpack\Status as Status;
14
use Automattic\Jetpack\Sync\Functions;
15
use Automattic\Jetpack\Tracking as Tracking;
16
use Jetpack_Options;
17
use Jetpack_Tracks_Client;
18
use WP_Error;
19
20
/**
21
 * This class will handle everything involved with fixing an Identity Crisis.
22
 *
23
 * @since 1.0.0
24
 */
25
class Identity_Crisis {
26
27
	/**
28
	 * Package Version
29
	 */
30
	const PACKAGE_VERSION = '1.0.0-alpha';
31
32
	/**
33
	 * Instance of the object.
34
	 *
35
	 * @var Identity_Crisis
36
	 **/
37
	private static $instance = null;
38
39
	/**
40
	 * The wpcom value of the home URL.
41
	 *
42
	 * @var string
43
	 */
44
	public static $wpcom_home_url;
45
46
	/**
47
	 * Has safe mode been confirmed?
48
	 *
49
	 * @var bool
50
	 */
51
	public static $is_safe_mode_confirmed;
52
53
	/**
54
	 * The current screen, which is set if the current user is a non-admin and this is an admin page.
55
	 *
56
	 * @var WP_Screen
57
	 */
58
	public static $current_screen;
59
60
	/**
61
	 * Initializer.
62
	 *
63
	 * @return object
64
	 */
65
	public static function init() {
66
		if ( is_null( self::$instance ) ) {
67
			self::$instance = new Identity_Crisis();
68
		}
69
70
		return self::$instance;
71
	}
72
73
	/**
74
	 * Class constructor.
75
	 *
76
	 * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
77
	 */
78 View Code Duplication
	private function __construct() {
79
		add_action( 'jetpack_sync_processed_actions', array( $this, 'maybe_clear_migrate_option' ) );
80
		$urls_in_crisis = self::check_identity_crisis();
81
		if ( false === $urls_in_crisis ) {
82
			return;
83
		}
84
85
		self::$wpcom_home_url = $urls_in_crisis['wpcom_home'];
86
		add_action( 'init', array( $this, 'wordpress_init' ) );
87
	}
88
89
	/**
90
	 * Gets the link to the support document used to explain Safe Mode to users.
91
	 *
92
	 * @return string
93
	 */
94
	public static function get_safe_mod_doc_url() {
95
		return Redirect::get_url( 'jetpack-support-safe-mode' );
96
	}
97
98
	/**
99
	 * This method loops through the array of processed items from sync and checks if one of the items was the
100
	 * home_url or site_url callable. If so, then we delete the jetpack_migrate_for_idc option.
101
	 *
102
	 * @param array $processed_items Array of processed items that were synced to WordPress.com.
103
	 */
104 View Code Duplication
	public function maybe_clear_migrate_option( $processed_items ) {
105
		foreach ( (array) $processed_items as $item ) {
106
107
			// First, is this item a jetpack_sync_callable action? If so, then proceed.
108
			$callable_args = ( is_array( $item ) && isset( $item[0], $item[1] ) && 'jetpack_sync_callable' === $item[0] )
109
				? $item[1]
110
				: null;
111
112
			// Second, if $callable_args is set, check if the callable was home_url or site_url. If so,
113
			// clear the migrate option.
114
			if (
115
				isset( $callable_args, $callable_args[0] )
116
				&& ( 'home_url' === $callable_args[0] || 'site_url' === $callable_args[1] )
117
			) {
118
				Jetpack_Options::delete_option( 'migrate_for_idc' );
119
				break;
120
			}
121
		}
122
	}
123
124
	/**
125
	 * WordPress init.
126
	 *
127
	 * @return void
128
	 */
129 View Code Duplication
	public function wordpress_init() {
130
		if ( ! current_user_can( 'jetpack_disconnect' ) && is_admin() ) {
131
			add_action( 'admin_notices', array( $this, 'display_non_admin_idc_notice' ) );
132
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_idc_notice_files' ) );
133
			add_action( 'current_screen', array( $this, 'non_admins_current_screen_check' ) );
134
135
			return;
136
		}
137
138
		if (
139
			isset( $_GET['jetpack_idc_clear_confirmation'], $_GET['_wpnonce'] ) &&
140
			wp_verify_nonce( $_GET['_wpnonce'], 'jetpack_idc_clear_confirmation' )
141
		) {
142
			Jetpack_Options::delete_option( 'safe_mode_confirmed' );
143
			self::$is_safe_mode_confirmed = false;
144
		} else {
145
			self::$is_safe_mode_confirmed = (bool) Jetpack_Options::get_option( 'safe_mode_confirmed' );
146
		}
147
148
		// 121 Priority so that it's the most inner Jetpack item in the admin bar.
149
		add_action( 'admin_bar_menu', array( $this, 'display_admin_bar_button' ), 121 );
150
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_bar_css' ) );
151
152
		if ( is_admin() && ! self::$is_safe_mode_confirmed ) {
153
			add_action( 'admin_notices', array( $this, 'display_idc_notice' ) );
154
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_idc_notice_files' ) );
155
		}
156
	}
157
158
	/**
159
	 * Non-admins current screen check.
160
	 *
161
	 * @param object $current_screen Current screen.
162
	 *
163
	 * @return null
164
	 */
165 View Code Duplication
	public function non_admins_current_screen_check( $current_screen ) {
166
		self::$current_screen = $current_screen;
167
		if ( isset( $current_screen->id ) && 'toplevel_page_jetpack' === $current_screen->id ) {
168
			return null;
169
		}
170
171
		// If the user has dismissed the notice, and we're not currently on a Jetpack page,
172
		// then do not show the non-admin notice.
173
		if ( isset( $_COOKIE, $_COOKIE['jetpack_idc_dismiss_notice'] ) ) {
174
			remove_action( 'admin_notices', array( $this, 'display_non_admin_idc_notice' ) );
175
			remove_action( 'admin_enqueue_scripts', array( $this, 'enqueue_idc_notice_files' ) );
176
		}
177
178
		return null;
179
	}
180
181
	/**
182
	 * Renders the admin bar button.
183
	 *
184
	 * @return void
185
	 */
186 View Code Duplication
	public function display_admin_bar_button() {
187
		global $wp_admin_bar;
188
189
		$href = is_admin()
190
			? add_query_arg( 'jetpack_idc_clear_confirmation', '1' )
191
			: add_query_arg( 'jetpack_idc_clear_confirmation', '1', admin_url() );
192
193
		$href = wp_nonce_url( $href, 'jetpack_idc_clear_confirmation' );
194
195
		$title = sprintf(
196
			'<span class="jp-idc-admin-bar">%s %s</span>',
197
			'<span class="dashicons dashicons-warning"></span>',
198
			esc_html__( 'Jetpack Safe Mode', 'jetpack' )
199
		);
200
201
		$menu = array(
202
			'id'     => 'jetpack-idc',
203
			'title'  => $title,
204
			'href'   => esc_url( $href ),
205
			'parent' => 'top-secondary',
206
		);
207
208
		if ( ! self::$is_safe_mode_confirmed ) {
209
			$menu['meta'] = array(
210
				'class' => 'hide',
211
			);
212
		}
213
214
		$wp_admin_bar->add_node( $menu );
215
	}
216
217
	/**
218
	 * Checks if the site is currently in an identity crisis.
219
	 *
220
	 * @return array|bool Array of options that are in a crisis, or false if everything is OK.
221
	 */
222
	public static function check_identity_crisis() {
223
		$connection = new Connection_Manager( 'jetpack' );
224
225
		if ( ! $connection->is_active() || ( new Status() )->is_offline_mode() || ! self::validate_sync_error_idc_option() ) {
0 ignored issues
show
Deprecated Code introduced by
The method Automattic\Jetpack\Connection\Manager::is_active() has been deprecated with message: 9.6.0

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
226
			return false;
227
		}
228
229
		return Jetpack_Options::get_option( 'sync_error_idc' );
230
	}
231
232
	/**
233
	 * Prepare URL for display.
234
	 *
235
	 * @param string $url URL to display.
236
	 *
237
	 * @return string
238
	 */
239
	public static function prepare_url_for_display( $url ) {
240
		return untrailingslashit( self::normalize_url_protocol_agnostic( $url ) );
241
	}
242
243
	/**
244
	 * Clears all IDC specific options. This method is used on disconnect and reconnect.
245
	 *
246
	 * @return void
247
	 */
248 View Code Duplication
	public static function clear_all_idc_options() {
249
		// If the site is currently in IDC, let's also clear the VaultPress connection options.
250
		// We have to check if the site is in IDC, otherwise we'd be clearing the VaultPress
251
		// connection any time the Jetpack connection is cycled.
252
		if ( self::validate_sync_error_idc_option() ) {
253
			delete_option( 'vaultpress' );
254
			delete_option( 'vaultpress_auto_register' );
255
		}
256
257
		Jetpack_Options::delete_option(
258
			array(
259
				'sync_error_idc',
260
				'safe_mode_confirmed',
261
				'migrate_for_idc',
262
			)
263
		);
264
	}
265
266
	/**
267
	 * Checks whether the sync_error_idc option is valid or not, and if not, will do cleanup.
268
	 *
269
	 * @return bool
270
	 *
271
	 * @since 1.0.0
272
	 */
273 View Code Duplication
	public static function validate_sync_error_idc_option() {
274
		$is_valid = false;
275
276
		// Is the site opted in and does the stored sync_error_idc option match what we now generate?
277
		$sync_error = Jetpack_Options::get_option( 'sync_error_idc' );
278
		if ( $sync_error && self::sync_idc_optin() ) {
279
			$local_options = self::get_sync_error_idc_option();
280
			// Ensure all values are set.
281
			if ( isset( $sync_error['home'] ) && isset( $local_options['home'] ) && isset( $sync_error['siteurl'] ) && isset( $local_options['siteurl'] ) ) {
282
				// If the WP.com expected home and siteurl match local home and siteurl it is not valid IDC.
283
				if (
284
					isset( $sync_error['wpcom_home'] ) &&
285
					isset( $sync_error['wpcom_siteurl'] ) &&
286
					$sync_error['wpcom_home'] === $local_options['home'] &&
287
					$sync_error['wpcom_siteurl'] === $local_options['siteurl']
288
				) {
289
					$is_valid = false;
290
					// Enable migrate_for_idc so that sync actions are accepted.
291
					Jetpack_Options::update_option( 'migrate_for_idc', true );
292
				} elseif ( $sync_error['home'] === $local_options['home'] && $sync_error['siteurl'] === $local_options['siteurl'] ) {
293
					$is_valid = true;
294
				}
295
			}
296
		}
297
298
		/**
299
		 * Filters whether the sync_error_idc option is valid.
300
		 *
301
		 * @param bool $is_valid If the sync_error_idc is valid or not.
302
		 *
303
		 * @since 1.0.0
304
		 */
305
		$is_valid = (bool) apply_filters( 'jetpack_sync_error_idc_validation', $is_valid );
306
307
		if ( ! $is_valid && $sync_error ) {
308
			// Since the option exists, and did not validate, delete it.
309
			Jetpack_Options::delete_option( 'sync_error_idc' );
310
		}
311
312
		return $is_valid;
313
	}
314
315
	/**
316
	 * Normalizes a url by doing three things:
317
	 *  - Strips protocol
318
	 *  - Strips www
319
	 *  - Adds a trailing slash
320
	 *
321
	 * @param string $url URL to parse.
322
	 *
323
	 * @return WP_Error|string
324
	 * @since 1.0.0
325
	 */
326 View Code Duplication
	public static function normalize_url_protocol_agnostic( $url ) {
327
		$parsed_url = wp_parse_url( trailingslashit( esc_url_raw( $url ) ) );
328
		if ( ! $parsed_url || empty( $parsed_url['host'] ) || empty( $parsed_url['path'] ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parsed_url of type string|false is loosely compared to false; 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...
329
			return new WP_Error(
330
				'cannot_parse_url',
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'cannot_parse_url'.

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...
331
				sprintf(
332
				/* translators: %s: URL to parse. */
333
					esc_html__( 'Cannot parse URL %s', 'jetpack' ),
334
					$url
335
				)
336
			);
337
		}
338
339
		// Strip www and protocols.
340
		$url = preg_replace( '/^www\./i', '', $parsed_url['host'] . $parsed_url['path'] );
341
342
		return $url;
343
	}
344
345
	/**
346
	 * Gets the value that is to be saved in the jetpack_sync_error_idc option.
347
	 *
348
	 * @param array $response HTTP response.
349
	 *
350
	 * @return array Array of the local urls, wpcom urls, and error code.
351
	 * @since 1.0.0
352
	 */
353 View Code Duplication
	public static function get_sync_error_idc_option( $response = array() ) {
354
		// Since the local options will hit the database directly, store the values
355
		// in a transient to allow for autoloading and caching on subsequent views.
356
		$local_options = get_transient( 'jetpack_idc_local' );
357
		if ( false === $local_options ) {
358
			$local_options = array(
359
				'home'    => Functions::home_url(),
360
				'siteurl' => Functions::site_url(),
361
			);
362
			set_transient( 'jetpack_idc_local', $local_options, MINUTE_IN_SECONDS );
363
		}
364
365
		$options = array_merge( $local_options, $response );
366
367
		$returned_values = array();
368
		foreach ( $options as $key => $option ) {
369
			if ( 'error_code' === $key ) {
370
				$returned_values[ $key ] = $option;
371
				continue;
372
			}
373
374
			$normalized_url = self::normalize_url_protocol_agnostic( $option );
375
			if ( is_wp_error( $normalized_url ) ) {
376
				continue;
377
			}
378
379
			$returned_values[ $key ] = $normalized_url;
380
		}
381
382
		set_transient( 'jetpack_idc_option', $returned_values, MINUTE_IN_SECONDS );
383
384
		return $returned_values;
385
	}
386
387
	/**
388
	 * Returns the value of the jetpack_sync_idc_optin filter, or constant.
389
	 * If set to true, the site will be put into staging mode.
390
	 *
391
	 * @return bool
392
	 * @since 1.0.0
393
	 */
394 View Code Duplication
	public static function sync_idc_optin() {
395
		if ( Constants::is_defined( 'JETPACK_SYNC_IDC_OPTIN' ) ) {
396
			$default = Constants::get_constant( 'JETPACK_SYNC_IDC_OPTIN' );
397
		} else {
398
			$default = ! Constants::is_defined( 'SUNRISE' ) && ! is_multisite();
399
		}
400
401
		/**
402
		 * Allows sites to opt in for IDC mitigation which blocks the site from syncing to WordPress.com when the home
403
		 * URL or site URL do not match what WordPress.com expects. The default value is either true, or the value of
404
		 * JETPACK_SYNC_IDC_OPTIN constant if set.
405
		 *
406
		 * @param bool $default Whether the site is opted in to IDC mitigation.
407
		 *
408
		 * @since 1.0.0
409
		 */
410
		return (bool) apply_filters( 'jetpack_sync_idc_optin', $default );
411
	}
412
413
	/**
414
	 * Does the current admin page have help tabs?
415
	 *
416
	 * @return bool
417
	 */
418 View Code Duplication
	public function admin_page_has_help_tabs() {
419
		if ( ! function_exists( 'get_current_screen' ) ) {
420
			return false;
421
		}
422
423
		$current_screen = get_current_screen();
424
		$tabs           = $current_screen->get_help_tabs();
425
426
		return ! empty( $tabs );
427
	}
428
429
	/**
430
	 * Renders the non-admin IDC notice.
431
	 *
432
	 * @return void
433
	 */
434
	public function display_non_admin_idc_notice() {
435
		$classes = 'jp-idc-notice inline is-non-admin notice notice-warning';
436
		if ( isset( self::$current_screen ) && 'toplevel_page_jetpack' !== self::$current_screen->id ) {
437
			$classes .= ' is-dismissible';
438
		}
439
440
		if ( $this->admin_page_has_help_tabs() ) {
441
			$classes .= ' has-help-tabs';
442
		}
443
		?>
444
445
		<div class="<?php echo esc_attr( $classes ); ?>">
446
			<?php $this->render_notice_header(); ?>
447
			<div class="jp-idc-notice__content-header">
448
				<h3 class="jp-idc-notice__content-header__lead">
449
					<?php echo esc_html( $this->get_non_admin_notice_text() ); ?>
450
				</h3>
451
452
				<p class="jp-idc-notice__content-header__explanation">
453
					<?php echo esc_html( $this->get_non_admin_contact_admin_text() ); ?>
454
				</p>
455
			</div>
456
		</div>
457
		<?php
458
	}
459
460
	/**
461
	 * First "step" of the IDC mitigation. Will provide some messaging and two options/buttons.
462
	 * "Confirm Staging" - Dismiss the notice and continue on with our lives in staging mode.
463
	 * "Fix Jetpack Connection" - Will disconnect the site and start the mitigation...
464
	 *
465
	 * @return void
466
	 */
467 View Code Duplication
	public function display_idc_notice() {
468
		$classes = 'jp-idc-notice inline notice notice-warning';
469
		if ( $this->admin_page_has_help_tabs() ) {
470
			$classes .= ' has-help-tabs';
471
		}
472
		?>
473
		<div class="<?php echo esc_attr( $classes ); ?>">
474
			<?php $this->render_notice_header(); ?>
475
			<?php $this->render_notice_first_step(); ?>
476
			<?php $this->render_notice_second_step(); ?>
477
		</div>
478
		<?php
479
	}
480
481
	/**
482
	 * Enqueue CSS for the admin bar.
483
	 *
484
	 * @return void
485
	 */
486
	public function enqueue_admin_bar_css() {
487
488
		$build_assets = require_once __DIR__ . '/../build/index.asset.php';
489
490
		wp_enqueue_style(
491
			'jetpack-idc-admin-bar-css',
492
			plugin_dir_url( __DIR__ ) . 'build/css/jetpack-idc-admin-bar.css',
493
			array( 'dashicons' ),
494
			$build_assets['version']
495
		);
496
	}
497
498
	/**
499
	 * Enqueue scripts for the notice.
500
	 *
501
	 * @return void
502
	 */
503
	public function enqueue_idc_notice_files() {
504
		$build_assets                   = require_once __DIR__ . '/../build/index.asset.php';
505
		$build_assets['dependencies'][] = 'jquery';
506
507
		wp_enqueue_script(
508
			'jetpack-idc-js',
509
			Assets::get_file_url_for_environment( 'build/index.js', 'build/index.js', plugin_dir_url( __DIR__ ) ),
510
			$build_assets['dependencies'],
511
			$build_assets['version'],
512
			true
513
		);
514
515
		wp_localize_script(
516
			'jetpack-idc-js',
517
			'idcL10n',
518
			array(
519
				'apiRoot'         => esc_url_raw( rest_url() ),
520
				'nonce'           => wp_create_nonce( 'wp_rest' ),
521
				'tracksUserData'  => Jetpack_Tracks_Client::get_connected_user_tracks_identity(),
522
				'currentUrl'      => remove_query_arg( '_wpnonce', remove_query_arg( 'jetpack_idc_clear_confirmation' ) ),
523
				'tracksEventData' => array(
524
					'isAdmin'       => current_user_can( 'jetpack_disconnect' ),
525
					'currentScreen' => self::$current_screen ? self::$current_screen->id : false,
526
				),
527
			)
528
		);
529
530
		if ( ! wp_style_is( 'jetpack-dops-style' ) ) {
531
			wp_register_style(
532
				'jetpack-dops-style',
533
				plugins_url( '_inc/build/admin.css', JETPACK__PLUGIN_FILE ), // TODO
534
				array(),
535
				self::PACKAGE_VERSION
536
			);
537
		}
538
539
		wp_enqueue_style(
540
			'jetpack-idc-admin-bar-css',
541
			plugin_dir_url( __DIR__ ) . 'build/css/jetpack-idc-admin-bar.css',
542
			array( 'jetpack-dops-style' ),
543
			self::PACKAGE_VERSION
544
		);
545
		wp_enqueue_style(
546
			'jetpack-idc-css',
547
			plugin_dir_url( __DIR__ ) . 'build/jetpack-idc.css',
548
			array( 'jetpack-dops-style' ),
549
			self::PACKAGE_VERSION
550
		);
551
552
		// Register and Enqueue jp-tracks-functions.
553
		Tracking::register_tracks_functions_scripts( true );
0 ignored issues
show
Bug introduced by
The method register_tracks_functions_scripts() does not seem to exist on object<Automattic\Jetpack\Tracking>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
554
	}
555
556
	/**
557
	 * Renders the notice header.
558
	 *
559
	 * @return void
560
	 */
561
	public function render_notice_header() {
562
		?>
563
		<div class="jp-idc-notice__header">
564
			<div class="jp-idc-notice__header__emblem">
565
				<?php
566
				$jetpack_logo = new Jetpack_Logo();
567
				echo esc_html( $jetpack_logo->get_jp_emblem() );
568
				?>
569
			</div>
570
			<p class="jp-idc-notice__header__text">
571
				<?php esc_html_e( 'Jetpack Safe Mode', 'jetpack' ); ?>
572
			</p>
573
		</div>
574
575
		<div class="jp-idc-notice__separator"></div>
576
		<?php
577
	}
578
579
	/**
580
	 * Is a container for the error notices.
581
	 * Will be shown/controlled by jQuery in idc-notice.js.
582
	 *
583
	 * @return void
584
	 */
585
	public function render_error_notice() {
586
		?>
587
		<div class="jp-idc-error__notice dops-notice is-error">
588
			<svg class="gridicon gridicons-notice dops-notice__icon" height="24" width="24" viewBox="0 0 24 24">
589
				<g>
590
					<path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm1 15h-2v-2h2v2zm0-4h-2l-.5-6h3l-.5 6z"></path>
591
				</g>
592
			</svg>
593
			<div class="dops-notice__content">
594
				<span class="dops-notice__text">
595
					<?php esc_html_e( 'Something went wrong:', 'jetpack' ); ?>
596
					<span class="jp-idc-error__desc"></span>
597
				</span>
598
				<a class="dops-notice__action" href="javascript:void(0);">
599
					<span id="jp-idc-error__action">
600
						<?php esc_html_e( 'Try Again', 'jetpack' ); ?>
601
					</span>
602
				</a>
603
			</div>
604
		</div>
605
		<?php
606
	}
607
608
	/**
609
	 * Renders the first step notice.
610
	 *
611
	 * @return void
612
	 */
613
	public function render_notice_first_step() {
614
		?>
615
		<div class="jp-idc-notice__first-step">
616
			<div class="jp-idc-notice__content-header">
617
				<h3 class="jp-idc-notice__content-header__lead">
618
					<?php echo esc_html( $this->get_first_step_header_lead() ); ?>
619
				</h3>
620
621
				<p class="jp-idc-notice__content-header__explanation">
622
					<?php echo esc_html( $this->get_first_step_header_explanation() ); ?>
623
				</p>
624
			</div>
625
626
			<?php $this->render_error_notice(); ?>
627
628
			<div class="jp-idc-notice__actions">
629
				<div class="jp-idc-notice__action">
630
					<p class="jp-idc-notice__action__explanation">
631
						<?php echo esc_html( $this->get_confirm_safe_mode_action_explanation() ); ?>
632
					</p>
633
					<button id="jp-idc-confirm-safe-mode-action" class="dops-button">
634
						<?php echo esc_html( $this->get_confirm_safe_mode_button_text() ); ?>
635
					</button>
636
				</div>
637
638
				<div class="jp-idc-notice__action">
639
					<p class="jp-idc-notice__action__explanation">
640
						<?php echo esc_html( $this->get_first_step_fix_connection_action_explanation() ); ?>
641
					</p>
642
					<button id="jp-idc-fix-connection-action" class="dops-button">
643
						<?php echo esc_html( $this->get_first_step_fix_connection_button_text() ); ?>
644
					</button>
645
				</div>
646
			</div>
647
		</div>
648
		<?php
649
	}
650
651
	/**
652
	 * Renders the second step notice.
653
	 *
654
	 * @return void
655
	 */
656
	public function render_notice_second_step() {
657
		?>
658
		<div class="jp-idc-notice__second-step">
659
			<div class="jp-idc-notice__content-header">
660
				<h3 class="jp-idc-notice__content-header__lead">
661
					<?php echo esc_html( $this->get_second_step_header_lead() ); ?>
662
				</h3>
663
			</div>
664
665
			<?php $this->render_error_notice(); ?>
666
667
			<div class="jp-idc-notice__actions">
668
				<div class="jp-idc-notice__action">
669
					<p class="jp-idc-notice__action__explanation">
670
						<?php echo esc_html( $this->get_migrate_site_action_explanation() ); ?>
671
					</p>
672
					<button id="jp-idc-migrate-action" class="dops-button">
673
						<?php echo esc_html( $this->get_migrate_site_button_text() ); ?>
674
					</button>
675
				</div>
676
677
				<div class="jp-idc-notice__action">
678
					<p class="jp-idc-notice__action__explanation">
679
						<?php echo esc_html( $this->get_start_fresh_action_explanation() ); ?>
680
					</p>
681
					<button id="jp-idc-reconnect-site-action" class="dops-button">
682
						<?php echo esc_html( $this->get_start_fresh_button_text() ); ?>
683
					</button>
684
				</div>
685
686
			</div>
687
688
			<p class="jp-idc-notice__unsure-prompt">
689
				<?php echo esc_html( $this->get_unsure_prompt() ); ?>
690
			</p>
691
		</div>
692
		<?php
693
	}
694
695
	/**
696
	 * Returns the first step header lead.
697
	 *
698
	 * @return string
699
	 */
700
	public function get_first_step_header_lead() {
701
		$html = wp_kses(
702
			sprintf(
703
			/* translators: %s: Safe mode docs URL and site URL. */
704
				__( 'Jetpack has been placed into <a href="%1$s">Safe mode</a> because we noticed this is an exact copy of <a href="%2$s">%3$s</a>.', 'jetpack' ),
705
				esc_url( self::get_safe_mod_doc_url() ),
706
				esc_url( self::$wpcom_home_url ),
707
				self::prepare_url_for_display( esc_url_raw( self::$wpcom_home_url ) )
708
			),
709
			array( 'a' => array( 'href' => array() ) )
710
		);
711
712
		/**
713
		 * Allows overriding of the default header text in the first step of the Safe Mode notice.
714
		 *
715
		 * @param string $html The HTML to be displayed.
716
		 *
717
		 * @since 1.0.0
718
		 */
719
		return apply_filters( 'jetpack_idc_first_step_header_lead', $html );
720
	}
721
722
	/**
723
	 * Returns the first step header explanation.
724
	 *
725
	 * @return string
726
	 */
727 View Code Duplication
	public function get_first_step_header_explanation() {
728
		$html = wp_kses(
729
			sprintf(
730
			/* translators: %s: Safe mode docs URL. */
731
				__( 'Please confirm Safe Mode or fix the Jetpack connection. Select one of the options below or <a href="%1$s">learn more about Safe Mode</a>.', 'jetpack' ),
732
				esc_url( self::get_safe_mod_doc_url() )
733
			),
734
			array( 'a' => array( 'href' => array() ) )
735
		);
736
737
		/**
738
		 * Allows overriding of the default header explanation text in the first step of the Safe Mode notice.
739
		 *
740
		 * @param string $html The HTML to be displayed.
741
		 *
742
		 * @since 1.0.0
743
		 */
744
		return apply_filters( 'jetpack_idc_first_step_header_explanation', $html );
745
	}
746
747
	/**
748
	 * Returns the confirm safe mode explanation.
749
	 *
750
	 * @return string
751
	 */
752
	public function get_confirm_safe_mode_action_explanation() {
753
		$html = wp_kses(
754
			sprintf(
755
			/* translators: %s: Site URL. */
756
				__( 'Is this website a temporary duplicate of <a href="%1$s">%2$s</a> for the purposes of testing, staging or development? If so, we recommend keeping it in Safe Mode.', 'jetpack' ),
757
				esc_url( untrailingslashit( self::$wpcom_home_url ) ),
758
				self::prepare_url_for_display( esc_url( self::$wpcom_home_url ) )
759
			),
760
			array( 'a' => array( 'href' => array() ) )
761
		);
762
763
		/**
764
		 * Allows overriding of the default text used to explain the confirm safe mode action.
765
		 *
766
		 * @param string $html The HTML to be displayed.
767
		 *
768
		 * @since 1.0.0
769
		 */
770
		return apply_filters( 'jetpack_idc_confirm_safe_mode_explanation', $html );
771
	}
772
773
	/**
774
	 * Returns the confirm safe mode button text.
775
	 *
776
	 * @return string
777
	 */
778
	public function get_confirm_safe_mode_button_text() {
779
		$string = esc_html__( 'Confirm Safe Mode', 'jetpack' );
780
781
		/**
782
		 * Allows overriding of the default text used for the confirm safe mode action button.
783
		 *
784
		 * @param string $string The string to be displayed.
785
		 *
786
		 * @since 1.0.0
787
		 */
788
		return apply_filters( 'jetpack_idc_confirm_safe_mode_button_text', $string );
789
	}
790
791
	/**
792
	 * Returns the first step fix connection action explanation.
793
	 *
794
	 * @return string
795
	 */
796
	public function get_first_step_fix_connection_action_explanation() {
797
		$html = wp_kses(
798
			sprintf(
799
			/* translators: %s: Site URL. */
800
				__( 'If this is a separate and new website, or the new home of <a href="%1$s">%2$s</a>, we recommend turning Safe Mode off, and re-establishing your connection to WordPress.com.', 'jetpack' ),
801
				esc_url( untrailingslashit( self::$wpcom_home_url ) ),
802
				self::prepare_url_for_display( esc_url( self::$wpcom_home_url ) )
803
			),
804
			array( 'a' => array( 'href' => array() ) )
805
		);
806
807
		/**
808
		 * Allows overriding of the default text used to explain the fix Jetpack connection action.
809
		 *
810
		 * @param string $html The HTML to be displayed.
811
		 *
812
		 * @since 1.0.0
813
		 */
814
		return apply_filters( 'jetpack_idc_first_fix_connection_explanation', $html );
815
	}
816
817
	/**
818
	 * Returns the first step fix connection button text.
819
	 *
820
	 * @return string
821
	 */
822
	public function get_first_step_fix_connection_button_text() {
823
		$string = esc_html__( "Fix Jetpack's Connection", 'jetpack' );
824
825
		/**
826
		 * Allows overriding of the default text used for the fix Jetpack connection action button.
827
		 *
828
		 * @param string $string The string to be displayed.
829
		 *
830
		 * @since 1.0.0
831
		 */
832
		return apply_filters( 'jetpack_idc_first_step_fix_connection_button_text', $string );
833
	}
834
835
	/**
836
	 * Returns the second step header lead.
837
	 *
838
	 * @return string
839
	 */
840 View Code Duplication
	public function get_second_step_header_lead() {
841
		$string = sprintf(
842
		/* translators: %s: Site URL. */
843
			esc_html__( 'Is %1$s the new home of %2$s?', 'jetpack' ),
844
			untrailingslashit( self::normalize_url_protocol_agnostic( get_home_url() ) ),
845
			untrailingslashit( self::normalize_url_protocol_agnostic( esc_url_raw( self::$wpcom_home_url ) ) )
846
		);
847
848
		/**
849
		 * Allows overriding of the default header text in the second step of the Safe Mode notice.
850
		 *
851
		 * @param string $html The HTML to be displayed.
852
		 *
853
		 * @since 1.0.0
854
		 */
855
		return apply_filters( 'jetpack_idc_second_step_header_lead', $string );
856
	}
857
858
	/**
859
	 * Returns the site action explanation.
860
	 *
861
	 * @return string
862
	 */
863 View Code Duplication
	public function get_migrate_site_action_explanation() {
864
		$html = wp_kses(
865
			sprintf(
866
			/* translators: %s: Site URL. */
867
				__( 'Yes. <a href="%1$s">%2$s</a> is replacing <a href="%3$s">%4$s</a>. I would like to migrate my stats and subscribers from <a href="%3$s">%4$s</a> to <a href="%1$s">%2$s</a>.', 'jetpack' ),
868
				esc_url( get_home_url() ),
869
				self::prepare_url_for_display( get_home_url() ),
870
				esc_url( self::$wpcom_home_url ),
871
				untrailingslashit( self::normalize_url_protocol_agnostic( esc_url_raw( self::$wpcom_home_url ) ) )
872
			),
873
			array( 'a' => array( 'href' => array() ) )
874
		);
875
876
		/**
877
		 * Allows overriding of the default text for explaining the migrate site action.
878
		 *
879
		 * @param string $html The HTML to be displayed.
880
		 *
881
		 * @since 1.0.0
882
		 */
883
		return apply_filters( 'jetpack_idc_migrate_site_explanation', $html );
884
	}
885
886
	/**
887
	 * Returns the migrate site button text.
888
	 *
889
	 * @return string
890
	 */
891
	public function get_migrate_site_button_text() {
892
		$string = esc_html__( 'Migrate Stats &amp; Subscribers', 'jetpack' );
893
894
		/**
895
		 * Allows overriding of the default text used for the migrate site action button.
896
		 *
897
		 * @param string $string The string to be displayed.
898
		 *
899
		 * @since 1.0.0
900
		 */
901
		return apply_filters( 'jetpack_idc_migrate_site_button_text', $string );
902
	}
903
904
	/**
905
	 * Returns the start fresh explanation.
906
	 *
907
	 * @return string
908
	 */
909 View Code Duplication
	public function get_start_fresh_action_explanation() {
910
		$html = wp_kses(
911
			sprintf(
912
			/* translators: %s: Site URL. */
913
				__( 'No. <a href="%1$s">%2$s</a> is a new and different website that\'s separate from <a href="%3$s">%4$s</a>. It requires  a new connection to WordPress.com for new stats and subscribers.', 'jetpack' ),
914
				esc_url( get_home_url() ),
915
				self::prepare_url_for_display( get_home_url() ),
916
				esc_url( self::$wpcom_home_url ),
917
				untrailingslashit( self::normalize_url_protocol_agnostic( esc_url_raw( self::$wpcom_home_url ) ) )
918
			),
919
			array( 'a' => array( 'href' => array() ) )
920
		);
921
922
		/**
923
		 * Allows overriding of the default text for explaining the start fresh action.
924
		 *
925
		 * @param string $html The HTML to be displayed.
926
		 *
927
		 * @since 1.0.0
928
		 */
929
		return apply_filters( 'jetpack_idc_start_fresh_explanation', $html );
930
	}
931
932
	/**
933
	 * Returns the start fresh button text.
934
	 *
935
	 * @return string
936
	 */
937
	public function get_start_fresh_button_text() {
938
		$string = esc_html__( 'Start Fresh &amp; Create New Connection', 'jetpack' );
939
940
		/**
941
		 * Allows overriding of the default text used for the start fresh action button.
942
		 *
943
		 * @param string $string The string to be displayed.
944
		 *
945
		 * @since 1.0.0
946
		 */
947
		return apply_filters( 'jetpack_idc_start_fresh_button_text', $string );
948
	}
949
950
	/**
951
	 * Returns the unsure prompt text.
952
	 *
953
	 * @return string
954
	 */
955 View Code Duplication
	public function get_unsure_prompt() {
956
		$html = wp_kses(
957
			sprintf(
958
			/* translators: %s: Safe mode docs URL. */
959
				__( 'Unsure what to do? <a href="%1$s">Read more about Jetpack Safe Mode</a>', 'jetpack' ),
960
				esc_url( self::get_safe_mod_doc_url() )
961
			),
962
			array( 'a' => array( 'href' => array() ) )
963
		);
964
965
		/**
966
		 * Allows overriding of the default text using in the "Unsure what to do?" prompt.
967
		 *
968
		 * @param string $html The HTML to be displayed.
969
		 *
970
		 * @since 1.0.0
971
		 */
972
		return apply_filters( 'jetpack_idc_unsure_prompt', $html );
973
	}
974
975
	/**
976
	 * Returns the non-admin notice text.
977
	 *
978
	 * @return string
979
	 */
980 View Code Duplication
	public function get_non_admin_notice_text() {
981
		$html = wp_kses(
982
			sprintf(
983
			/* translators: %s: Safe mode docs URL. */
984
				__( 'Jetpack has been placed into Safe Mode. Learn more about <a href="%1$s">Safe Mode</a>.', 'jetpack' ),
985
				esc_url( self::get_safe_mod_doc_url() )
986
			),
987
			array( 'a' => array( 'href' => array() ) )
988
		);
989
990
		/**
991
		 * Allows overriding of the default text that is displayed to non-admin on the Jetpack admin page.
992
		 *
993
		 * @param string $html The HTML to be displayed.
994
		 *
995
		 * @since 1.0.0
996
		 */
997
		return apply_filters( 'jetpack_idc_non_admin_notice_text', $html );
998
	}
999
1000
	/**
1001
	 * Returns the non-admin contact admin text.
1002
	 *
1003
	 * @return string
1004
	 */
1005
	public function get_non_admin_contact_admin_text() {
1006
		$string = esc_html__( 'An administrator of this site can take Jetpack out of Safe Mode.', 'jetpack' );
1007
1008
		/**
1009
		 * Allows overriding of the default text that is displayed to non-admins prompting them to contact an admin.
1010
		 *
1011
		 * @param string $string The string to be displayed.
1012
		 *
1013
		 * @since 1.0.0
1014
		 */
1015
		return apply_filters( 'jetpack_idc_non_admin_contact_admin_text', $string );
1016
	}
1017
}
1018
1019
add_action( 'plugins_loaded', array( 'Identity_Crisis', 'init' ) );
1020