PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 7.8.3
Jetpack – WP Security, Backup, Speed, & Growth v7.8.3
12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 14.4.2 All 500 releases
jetpack / class.jetpack-idc.php
class.jetpack-idc.php
721 lines 20.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use Automattic\Jetpack\Assets;
4 use Automattic\Jetpack\Assets\Logo as Jetpack_Logo;
5
6 /**
7 * This class will handle everything involved with fixing an Identity Crisis.
8 *
9 * @since 4.4.0
10 */
11 class Jetpack_IDC {
12
13 /**
14 * @var Jetpack_IDC
15 **/
16 private static $instance = null;
17
18 /**
19 * The wpcom value of the home URL
20 *
21 * @var string
22 */
23 static $wpcom_home_url;
24
25 /**
26 * Has safe mode been confirmed?
27 *
28 * @var bool
29 */
30 static $is_safe_mode_confirmed;
31
32 /**
33 * The current screen, which is set if the current user is a non-admin and this is an admin page.
34 *
35 * @var WP_Screen
36 */
37 static $current_screen;
38
39 /**
40 * The link to the support document used to explain Safe Mode to users
41 *
42 * @var string
43 */
44 const SAFE_MODE_DOC_LINK = 'https://jetpack.com/support/safe-mode';
45
46 static function init() {
47 if ( is_null( self::$instance ) ) {
48 self::$instance = new Jetpack_IDC();
49 }
50
51 return self::$instance;
52 }
53
54 private function __construct() {
55 add_action( 'jetpack_sync_processed_actions', array( $this, 'maybe_clear_migrate_option' ) );
56
57 if ( false === $urls_in_crisis = Jetpack::check_identity_crisis() ) {
58 return;
59 }
60
61 self::$wpcom_home_url = $urls_in_crisis['wpcom_home'];
62 add_action( 'init', array( $this, 'wordpress_init' ) );
63 }
64
65 /**
66 * This method loops through the array of processed items from sync and checks if one of the items was the
67 * home_url or site_url callable. If so, then we delete the jetpack_migrate_for_idc option.
68 *
69 * @param $processed_items array Array of processed items that were synced to WordPress.com
70 */
71 function maybe_clear_migrate_option( $processed_items ) {
72 foreach ( (array) $processed_items as $item ) {
73
74 // First, is this item a jetpack_sync_callable action? If so, then proceed.
75 $callable_args = ( is_array( $item ) && isset( $item[0], $item[1] ) && 'jetpack_sync_callable' === $item[0] )
76 ? $item[1]
77 : null;
78
79 // Second, if $callable_args is set, check if the callable was home_url or site_url. If so,
80 // clear the migrate option.
81 if (
82 isset( $callable_args, $callable_args[0] )
83 && ( 'home_url' === $callable_args[0] || 'site_url' === $callable_args[1] )
84 ) {
85 Jetpack_Options::delete_option( 'migrate_for_idc' );
86 break;
87 }
88 }
89 }
90
91 function wordpress_init() {
92 if ( ! current_user_can( 'jetpack_disconnect' ) && is_admin() ) {
93 add_action( 'admin_notices', array( $this, 'display_non_admin_idc_notice' ) );
94 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_idc_notice_files' ) );
95 add_action( 'current_screen', array( $this, 'non_admins_current_screen_check' ) );
96 return;
97 }
98
99 if (
100 isset( $_GET['jetpack_idc_clear_confirmation'], $_GET['_wpnonce'] ) &&
101 wp_verify_nonce( $_GET['_wpnonce'], 'jetpack_idc_clear_confirmation' )
102 ) {
103 Jetpack_Options::delete_option( 'safe_mode_confirmed' );
104 self::$is_safe_mode_confirmed = false;
105 } else {
106 self::$is_safe_mode_confirmed = (bool) Jetpack_Options::get_option( 'safe_mode_confirmed' );
107 }
108
109 // 121 Priority so that it's the most inner Jetpack item in the admin bar.
110 add_action( 'admin_bar_menu', array( $this, 'display_admin_bar_button' ), 121 );
111 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_bar_css' ) );
112
113 if ( is_admin() && ! self::$is_safe_mode_confirmed ) {
114 add_action( 'admin_notices', array( $this, 'display_idc_notice' ) );
115 add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_idc_notice_files' ) );
116 }
117 }
118
119 function non_admins_current_screen_check( $current_screen ) {
120 self::$current_screen = $current_screen;
121 if ( isset( $current_screen->id ) && 'toplevel_page_jetpack' == $current_screen->id ) {
122 return null;
123 }
124
125 // If the user has dismissed the notice, and we're not currently on a Jetpack page,
126 // then do not show the non-admin notice.
127 if ( isset( $_COOKIE, $_COOKIE['jetpack_idc_dismiss_notice'] ) ) {
128 remove_action( 'admin_notices', array( $this, 'display_non_admin_idc_notice' ) );
129 remove_action( 'admin_enqueue_scripts', array( $this, 'enqueue_idc_notice_files' ) );
130 }
131 }
132
133 function display_admin_bar_button() {
134 global $wp_admin_bar;
135
136 $href = is_admin()
137 ? add_query_arg( 'jetpack_idc_clear_confirmation', '1' )
138 : add_query_arg( 'jetpack_idc_clear_confirmation', '1', admin_url() );
139
140 $href = wp_nonce_url( $href, 'jetpack_idc_clear_confirmation' );
141
142 $title = sprintf(
143 '<span class="jp-idc-admin-bar">%s %s</span>',
144 '<span class="dashicons dashicons-warning"></span>',
145 esc_html__( 'Jetpack Safe Mode', 'jetpack' )
146 );
147
148 $menu = array(
149 'id' => 'jetpack-idc',
150 'title' => $title,
151 'href' => esc_url( $href ),
152 'parent' => 'top-secondary',
153 );
154
155 if ( ! self::$is_safe_mode_confirmed ) {
156 $menu['meta'] = array(
157 'class' => 'hide',
158 );
159 }
160
161 $wp_admin_bar->add_node( $menu );
162 }
163
164 static function prepare_url_for_display( $url ) {
165 return untrailingslashit( Jetpack::normalize_url_protocol_agnostic( $url ) );
166 }
167
168 /**
169 * Clears all IDC specific options. This method is used on disconnect and reconnect.
170 */
171 static function clear_all_idc_options() {
172 // If the site is currently in IDC, let's also clear the VaultPress connection options.
173 // We have to check if the site is in IDC, otherwise we'd be clearing the VaultPress
174 // connection any time the Jetpack connection is cycled.
175 if ( Jetpack::validate_sync_error_idc_option() ) {
176 delete_option( 'vaultpress' );
177 delete_option( 'vaultpress_auto_register' );
178 }
179
180 Jetpack_Options::delete_option(
181 array(
182 'sync_error_idc',
183 'safe_mode_confirmed',
184 'migrate_for_idc',
185 )
186 );
187 }
188
189 /**
190 * Does the current admin page have help tabs?
191 *
192 * @return bool
193 */
194 function admin_page_has_help_tabs() {
195 if ( ! function_exists( 'get_current_screen' ) ) {
196 return false;
197 }
198
199 $current_screen = get_current_screen();
200 $tabs = $current_screen->get_help_tabs();
201
202 return ! empty( $tabs );
203 }
204
205 function display_non_admin_idc_notice() {
206 $classes = 'jp-idc-notice inline is-non-admin notice notice-warning';
207 if ( isset( self::$current_screen ) && 'toplevel_page_jetpack' != self::$current_screen->id ) {
208 $classes .= ' is-dismissible';
209 }
210
211 if ( $this->admin_page_has_help_tabs() ) {
212 $classes .= ' has-help-tabs';
213 }
214 ?>
215
216 <div class="<?php echo $classes; ?>">
217 <?php $this->render_notice_header(); ?>
218 <div class="jp-idc-notice__content-header">
219 <h3 class="jp-idc-notice__content-header__lead">
220 <?php echo $this->get_non_admin_notice_text(); ?>
221 </h3>
222
223 <p class="jp-idc-notice__content-header__explanation">
224 <?php echo $this->get_non_admin_contact_admin_text(); ?>
225 </p>
226 </div>
227 </div>
228 <?php
229 }
230
231 /**
232 * First "step" of the IDC mitigation. Will provide some messaging and two options/buttons.
233 * "Confirm Staging" - Dismiss the notice and continue on with our lives in staging mode.
234 * "Fix Jetpack Connection" - Will disconnect the site and start the mitigation...
235 */
236 function display_idc_notice() {
237 $classes = 'jp-idc-notice inline notice notice-warning';
238 if ( $this->admin_page_has_help_tabs() ) {
239 $classes .= ' has-help-tabs';
240 }
241 ?>
242 <div class="<?php echo $classes; ?>">
243 <?php $this->render_notice_header(); ?>
244 <?php $this->render_notice_first_step(); ?>
245 <?php $this->render_notice_second_step(); ?>
246 </div>
247 <?php
248 }
249
250 function enqueue_admin_bar_css() {
251 wp_enqueue_style(
252 'jetpack-idc-admin-bar-css',
253 plugins_url( 'css/jetpack-idc-admin-bar.css', JETPACK__PLUGIN_FILE ),
254 array( 'dashicons' ),
255 JETPACK__VERSION
256 );
257 }
258
259 /**
260 * Enqueue scripts for the notice
261 */
262 function enqueue_idc_notice_files() {
263
264 wp_enqueue_script(
265 'jetpack-idc-js',
266 Assets::get_file_url_for_environment( '_inc/build/idc-notice.min.js', '_inc/idc-notice.js' ),
267 array( 'jquery' ),
268 JETPACK__VERSION,
269 true
270 );
271
272 wp_localize_script(
273 'jetpack-idc-js',
274 'idcL10n',
275 array(
276 'apiRoot' => esc_url_raw( rest_url() ),
277 'nonce' => wp_create_nonce( 'wp_rest' ),
278 'tracksUserData' => Jetpack_Tracks_Client::get_connected_user_tracks_identity(),
279 'currentUrl' => remove_query_arg( '_wpnonce', remove_query_arg( 'jetpack_idc_clear_confirmation' ) ),
280 'tracksEventData' => array(
281 'isAdmin' => current_user_can( 'jetpack_disconnect' ),
282 'currentScreen' => self::$current_screen ? self::$current_screen->id : false,
283 ),
284 )
285 );
286
287 if ( ! wp_style_is( 'jetpack-dops-style' ) ) {
288 wp_register_style(
289 'jetpack-dops-style',
290 plugins_url( '_inc/build/admin.css', JETPACK__PLUGIN_FILE ),
291 array(),
292 JETPACK__VERSION
293 );
294 }
295
296 wp_enqueue_style(
297 'jetpack-idc-css',
298 plugins_url( 'css/jetpack-idc.css', JETPACK__PLUGIN_FILE ),
299 array( 'jetpack-dops-style' ),
300 JETPACK__VERSION
301 );
302
303 // Required for Tracks
304 wp_enqueue_script(
305 'jp-tracks',
306 '//stats.wp.com/w.js',
307 array(),
308 gmdate( 'YW' ),
309 true
310 );
311
312 wp_enqueue_script(
313 'jp-tracks-functions',
314 plugins_url( '_inc/lib/tracks/tracks-callables.js', JETPACK__PLUGIN_FILE ),
315 array(),
316 JETPACK__VERSION,
317 false
318 );
319 }
320
321 function render_notice_header() {
322 ?>
323 <div class="jp-idc-notice__header">
324 <div class="jp-idc-notice__header__emblem">
325 <?php
326 $jetpack_logo = new Jetpack_Logo();
327 echo $jetpack_logo->get_jp_emblem();
328 ?>
329 </div>
330 <p class="jp-idc-notice__header__text">
331 <?php esc_html_e( 'Jetpack Safe Mode', 'jetpack' ); ?>
332 </p>
333 </div>
334
335 <div class="jp-idc-notice__separator"></div>
336 <?php
337 }
338
339 /**
340 * Is a container for the error notices.
341 * Will be shown/controlled by jQuery in idc-notice.js
342 */
343 function render_error_notice() {
344 ?>
345 <div class="jp-idc-error__notice dops-notice is-error">
346 <svg class="gridicon gridicons-notice dops-notice__icon" height="24" width="24" viewBox="0 0 24 24">
347 <g>
348 <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>
349 </g>
350 </svg>
351 <div class="dops-notice__content">
352 <span class="dops-notice__text">
353 <?php esc_html_e( 'Something went wrong:', 'jetpack' ); ?>
354 <span class="jp-idc-error__desc"></span>
355 </span>
356 <a class="dops-notice__action" href="javascript:void(0);">
357 <span id="jp-idc-error__action">
358 <?php esc_html_e( 'Try Again', 'jetpack' ); ?>
359 </span>
360 </a>
361 </div>
362 </div>
363 <?php
364 }
365
366 function render_notice_first_step() {
367 ?>
368 <div class="jp-idc-notice__first-step">
369 <div class="jp-idc-notice__content-header">
370 <h3 class="jp-idc-notice__content-header__lead">
371 <?php echo $this->get_first_step_header_lead(); ?>
372 </h3>
373
374 <p class="jp-idc-notice__content-header__explanation">
375 <?php echo $this->get_first_step_header_explanation(); ?>
376 </p>
377 </div>
378
379 <?php $this->render_error_notice(); ?>
380
381 <div class="jp-idc-notice__actions">
382 <div class="jp-idc-notice__action">
383 <p class="jp-idc-notice__action__explanation">
384 <?php echo $this->get_confirm_safe_mode_action_explanation(); ?>
385 </p>
386 <button id="jp-idc-confirm-safe-mode-action" class="dops-button">
387 <?php echo $this->get_confirm_safe_mode_button_text(); ?>
388 </button>
389 </div>
390
391 <div class="jp-idc-notice__action">
392 <p class="jp-idc-notice__action__explanation">
393 <?php echo $this->get_first_step_fix_connection_action_explanation(); ?>
394 </p>
395 <button id="jp-idc-fix-connection-action" class="dops-button">
396 <?php echo $this->get_first_step_fix_connection_button_text(); ?>
397 </button>
398 </div>
399 </div>
400 </div>
401 <?php
402 }
403
404 function render_notice_second_step() {
405 ?>
406 <div class="jp-idc-notice__second-step">
407 <div class="jp-idc-notice__content-header">
408 <h3 class="jp-idc-notice__content-header__lead">
409 <?php echo $this->get_second_step_header_lead(); ?>
410 </h3>
411 </div>
412
413 <?php $this->render_error_notice(); ?>
414
415 <div class="jp-idc-notice__actions">
416 <div class="jp-idc-notice__action">
417 <p class="jp-idc-notice__action__explanation">
418 <?php echo $this->get_migrate_site_action_explanation(); ?>
419 </p>
420 <button id="jp-idc-migrate-action" class="dops-button">
421 <?php echo $this->get_migrate_site_button_text(); ?>
422 </button>
423 </div>
424
425 <div class="jp-idc-notice__action">
426 <p class="jp-idc-notice__action__explanation">
427 <?php echo $this->get_start_fresh_action_explanation(); ?>
428 </p>
429 <button id="jp-idc-reconnect-site-action" class="dops-button">
430 <?php echo $this->get_start_fresh_button_text(); ?>
431 </button>
432 </div>
433
434 </div>
435
436 <p class="jp-idc-notice__unsure-prompt">
437 <?php echo $this->get_unsure_prompt(); ?>
438 </p>
439 </div>
440 <?php
441 }
442
443 function get_first_step_header_lead() {
444 $html = wp_kses(
445 sprintf(
446 __(
447 '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>.',
448 'jetpack'
449 ),
450 esc_url( self::SAFE_MODE_DOC_LINK ),
451 esc_url( self::$wpcom_home_url ),
452 self::prepare_url_for_display( esc_url_raw( self::$wpcom_home_url ) )
453 ),
454 array( 'a' => array( 'href' => array() ) )
455 );
456
457 /**
458 * Allows overriding of the default header text in the first step of the Safe Mode notice.
459 *
460 * @since 4.4.0
461 *
462 * @param string $html The HTML to be displayed
463 */
464 return apply_filters( 'jetpack_idc_first_step_header_lead', $html );
465 }
466
467 function get_first_step_header_explanation() {
468 $html = wp_kses(
469 sprintf(
470 __(
471 'Please confirm Safe Mode or fix the Jetpack connection. Select one of the options below or <a href="%1$s">learn
472 more about Safe Mode</a>.',
473 'jetpack'
474 ),
475 esc_url( self::SAFE_MODE_DOC_LINK )
476 ),
477 array( 'a' => array( 'href' => array() ) )
478 );
479
480 /**
481 * Allows overriding of the default header explanation text in the first step of the Safe Mode notice.
482 *
483 * @since 4.4.0
484 *
485 * @param string $html The HTML to be displayed
486 */
487 return apply_filters( 'jetpack_idc_first_step_header_explanation', $html );
488 }
489
490 function get_confirm_safe_mode_action_explanation() {
491 $html = wp_kses(
492 sprintf(
493 __(
494 'Is this website a temporary duplicate of <a href="%1$s">%2$s</a> for the purposes
495 of testing, staging or development? If so, we recommend keeping it in Safe Mode.',
496 'jetpack'
497 ),
498 esc_url( untrailingslashit( self::$wpcom_home_url ) ),
499 self::prepare_url_for_display( esc_url( self::$wpcom_home_url ) )
500 ),
501 array( 'a' => array( 'href' => array() ) )
502 );
503
504 /**
505 * Allows overriding of the default text used to explain the confirm safe mode action.
506 *
507 * @since 4.4.0
508 *
509 * @param string $html The HTML to be displayed
510 */
511 return apply_filters( 'jetpack_idc_confirm_safe_mode_explanation', $html );
512 }
513
514 function get_confirm_safe_mode_button_text() {
515 $string = esc_html__( 'Confirm Safe Mode', 'jetpack' );
516
517 /**
518 * Allows overriding of the default text used for the confirm safe mode action button.
519 *
520 * @since 4.4.0
521 *
522 * @param string $string The string to be displayed
523 */
524 return apply_filters( 'jetpack_idc_confirm_safe_mode_button_text', $string );
525 }
526
527 function get_first_step_fix_connection_action_explanation() {
528 $html = wp_kses(
529 sprintf(
530 __(
531 'If this is a separate and new website, or the new home of <a href="%1$s">%2$s</a>,
532 we recommend turning Safe Mode off, and re-establishing your connection to WordPress.com.',
533 'jetpack'
534 ),
535 esc_url( untrailingslashit( self::$wpcom_home_url ) ),
536 self::prepare_url_for_display( esc_url( self::$wpcom_home_url ) )
537 ),
538 array( 'a' => array( 'href' => array() ) )
539 );
540
541 /**
542 * Allows overriding of the default text used to explain the fix Jetpack connection action.
543 *
544 * @since 4.4.0
545 *
546 * @param string $html The HTML to be displayed
547 */
548 return apply_filters( 'jetpack_idc_first_fix_connection_explanation', $html );
549 }
550
551 function get_first_step_fix_connection_button_text() {
552 $string = esc_html__( "Fix Jetpack's Connection", 'jetpack' );
553
554 /**
555 * Allows overriding of the default text used for the fix Jetpack connection action button.
556 *
557 * @since 4.4.0
558 *
559 * @param string $string The string to be displayed
560 */
561 return apply_filters( 'jetpack_idc_first_step_fix_connection_button_text', $string );
562 }
563
564 function get_second_step_header_lead() {
565 $string = sprintf(
566 esc_html__(
567 'Is %1$s the new home of %2$s?',
568 'jetpack'
569 ),
570 untrailingslashit( Jetpack::normalize_url_protocol_agnostic( get_home_url() ) ),
571 untrailingslashit( Jetpack::normalize_url_protocol_agnostic( esc_url_raw( self::$wpcom_home_url ) ) )
572 );
573
574 /**
575 * Allows overriding of the default header text in the second step of the Safe Mode notice.
576 *
577 * @since 4.4.0
578 *
579 * @param string $html The HTML to be displayed
580 */
581 return apply_filters( 'jetpack_idc_second_step_header_lead', $string );
582 }
583
584 function get_migrate_site_action_explanation() {
585 $html = wp_kses(
586 sprintf(
587 __(
588 'Yes. <a href="%1$s">%2$s</a> is replacing <a href="%3$s">%4$s</a>. I would like to
589 migrate my stats and subscribers from <a href="%3$s">%4$s</a> to <a href="%1$s">%2$s</a>.',
590 'jetpack'
591 ),
592 esc_url( get_home_url() ),
593 self::prepare_url_for_display( get_home_url() ),
594 esc_url( self::$wpcom_home_url ),
595 untrailingslashit( Jetpack::normalize_url_protocol_agnostic( esc_url_raw( self::$wpcom_home_url ) ) )
596 ),
597 array( 'a' => array( 'href' => array() ) )
598 );
599
600 /**
601 * Allows overriding of the default text for explaining the migrate site action.
602 *
603 * @since 4.4.0
604 *
605 * @param string $html The HTML to be displayed
606 */
607 return apply_filters( 'jetpack_idc_migrate_site_explanation', $html );
608 }
609
610 function get_migrate_site_button_text() {
611 $string = esc_html__( 'Migrate Stats &amp; Subscribers', 'jetpack' );
612
613 /**
614 * Allows overriding of the default text used for the migrate site action button.
615 *
616 * @since 4.4.0
617 *
618 * @param string $string The string to be displayed
619 */
620 return apply_filters( 'jetpack_idc_migrate_site_button_text', $string );
621 }
622
623 function get_start_fresh_action_explanation() {
624 $html = wp_kses(
625 sprintf(
626 __(
627 'No. <a href="%1$s">%2$s</a> is a new and different website that\'s separate from
628 <a href="%3$s">%4$s</a>. It requires a new connection to WordPress.com for new stats and subscribers.',
629 'jetpack'
630 ),
631 esc_url( get_home_url() ),
632 self::prepare_url_for_display( get_home_url() ),
633 esc_url( self::$wpcom_home_url ),
634 untrailingslashit( Jetpack::normalize_url_protocol_agnostic( esc_url_raw( self::$wpcom_home_url ) ) )
635 ),
636 array( 'a' => array( 'href' => array() ) )
637 );
638
639 /**
640 * Allows overriding of the default text for explaining the start fresh action.
641 *
642 * @since 4.4.0
643 *
644 * @param string $html The HTML to be displayed
645 */
646 return apply_filters( 'jetpack_idc_start_fresh_explanation', $html );
647 }
648
649 function get_start_fresh_button_text() {
650 $string = esc_html__( 'Start Fresh &amp; Create New Connection', 'jetpack' );
651
652 /**
653 * Allows overriding of the default text used for the start fresh action button.
654 *
655 * @since 4.4.0
656 *
657 * @param string $string The string to be displayed
658 */
659 return apply_filters( 'jetpack_idc_start_fresh_button_text', $string );
660 }
661
662 function get_unsure_prompt() {
663 $html = wp_kses(
664 sprintf(
665 __(
666 'Unsure what to do? <a href="%1$s">Read more about Jetpack Safe Mode</a>',
667 'jetpack'
668 ),
669 esc_url( self::SAFE_MODE_DOC_LINK )
670 ),
671 array( 'a' => array( 'href' => array() ) )
672 );
673
674 /**
675 * Allows overriding of the default text using in the "Unsure what to do?" prompt.
676 *
677 * @since 4.4.0
678 *
679 * @param string $html The HTML to be displayed
680 */
681 return apply_filters( 'jetpack_idc_unsure_prompt', $html );
682 }
683
684 function get_non_admin_notice_text() {
685 $html = wp_kses(
686 sprintf(
687 __(
688 'Jetpack has been placed into Safe Mode. Learn more about <a href="%1$s">Safe Mode</a>.',
689 'jetpack'
690 ),
691 esc_url( self::SAFE_MODE_DOC_LINK )
692 ),
693 array( 'a' => array( 'href' => array() ) )
694 );
695
696 /**
697 * Allows overriding of the default text that is displayed to non-admin on the Jetpack admin page.
698 *
699 * @since 4.4.0
700 *
701 * @param string $html The HTML to be displayed
702 */
703 return apply_filters( 'jetpack_idc_non_admin_notice_text', $html );
704 }
705
706 function get_non_admin_contact_admin_text() {
707 $string = esc_html__( 'An administrator of this site can take Jetpack out of Safe Mode.', 'jetpack' );
708
709 /**
710 * Allows overriding of the default text that is displayed to non-admins prompting them to contact an admin.
711 *
712 * @since 4.4.0
713 *
714 * @param string $string The string to be displayed
715 */
716 return apply_filters( 'jetpack_idc_non_admin_contact_admin_text', $string );
717 }
718 }
719
720 Jetpack_IDC::init();
721