PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.2
Jetpack – WP Security, Backup, Speed, & Growth v16.2
16.2 16.2-beta 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 All 502 releases
← All changes | modules/subscriptions.php +220 -163 12.4.216.2 View file →
@@ -1,25 +1,38 @@
1 1 <?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName)
2 2 /**
3 3 * Module Name: Newsletter
4 - * Module Description: Let visitors subscribe to new posts and comments via email
4 + * Module Description: Grow your subscriber list and deliver your content directly to their email inbox.
5 5 * Sort Order: 9
6 6 * Recommendation Order: 8
7 7 * First Introduced: 1.2
8 8 * Requires Connection: Yes
9 9 * Requires User Connection: Yes
10 - * Auto Activate: No
10 + * Auto Activate: Yes
11 11 * Module Tags: Social
12 12 * Feature: Engagement
13 - * Additional Search Queries: subscriptions, subscription, email, follow, followers, subscribers, signup, newsletter
13 + * Additional Search Queries: subscriptions, subscription, email, follow, followers, subscribers, signup, newsletter, creator
14 14 */
15 15
16 16 // phpcs:disable Universal.Files.SeparateFunctionsFromOO.Mixed -- TODO: Move classes to appropriately-named class files.
17 17
18 +use Automattic\Jetpack\Admin_UI\Admin_Menu;
19 +use Automattic\Jetpack\Connection\Manager as Connection_Manager;
18 20 use Automattic\Jetpack\Connection\XMLRPC_Async_Call;
21 +use Automattic\Jetpack\Newsletter\Settings as Newsletter_Settings;
22 +use Automattic\Jetpack\Redirect;
23 +use Automattic\Jetpack\Status;
24 +use Automattic\Jetpack\Status\Host;
19 25
26 +if ( ! defined( 'ABSPATH' ) ) {
27 + exit( 0 );
28 +}
29 +
20 30 add_action( 'jetpack_modules_loaded', 'jetpack_subscriptions_load' );
21 31
32 +// Loads the User Content Link Redirection feature.
33 +require_once __DIR__ . '/subscriptions/jetpack-user-content-link-redirection.php';
34 +
22 35 /**
23 36 * Loads the Subscriptions module.
24 37 */
25 38 function jetpack_subscriptions_load() {
@@ -36,13 +49,13 @@
36 49 function jetpack_subscriptions_cherry_pick_server_data() {
37 50 $data = array();
38 51
39 52 foreach ( $_SERVER as $key => $value ) {
40 - if ( ! is_string( $value ) || 0 === strpos( $key, 'HTTP_COOKIE' ) ) {
53 + if ( ! is_string( $value ) || str_starts_with( $key, 'HTTP_COOKIE' ) ) {
41 54 continue;
42 55 }
43 56
44 - if ( 0 === strpos( $key, 'HTTP_' ) || in_array( $key, array( 'REMOTE_ADDR', 'REQUEST_URI', 'DOCUMENT_URI' ), true ) ) {
57 + if ( str_starts_with( $key, 'HTTP_' ) || in_array( $key, array( 'REMOTE_ADDR', 'REQUEST_URI', 'DOCUMENT_URI' ), true ) ) {
45 58 $data[ $key ] = $value;
46 59 }
47 60 }
48 61
@@ -50,8 +63,10 @@
50 63 }
51 64
52 65 /**
53 66 * Main class file for the Subscriptions module.
67 + *
68 + * @phan-constructor-used-for-side-effects
54 69 */
55 70 class Jetpack_Subscriptions {
56 71 /**
57 72 * Whether Jetpack has been instantiated or not.
@@ -120,12 +135,31 @@
120 135 add_filter( 'post_updated_messages', array( $this, 'update_published_message' ), 18, 1 );
121 136
122 137 // Set "social_notifications_subscribe" option during the first-time activation.
123 138 add_action( 'jetpack_activate_module_subscriptions', array( $this, 'set_social_notifications_subscribe' ) );
139 + add_action( 'jetpack_activate_module_subscriptions', array( $this, 'set_featured_image_in_email_default' ) );
140 + add_action( 'jetpack_activate_module_subscriptions', array( $this, 'set_newsletter_send_default' ) );
124 141
125 142 // Hide subscription messaging in Publish panel for posts that were published in the past
126 143 add_action( 'init', array( $this, 'register_post_meta' ), 20 );
127 144 add_action( 'transition_post_status', array( $this, 'maybe_set_first_published_status' ), 10, 3 );
145 +
146 + // Add Subscribers menu to Jetpack navigation.
147 + add_action( 'jetpack_admin_menu', array( $this, 'add_subscribers_menu' ) );
148 +
149 + // Customize the configuration URL to lead to the Subscriptions settings.
150 + add_filter(
151 + 'jetpack_module_configuration_url_subscriptions',
152 + function () {
153 + return Jetpack::admin_url( array( 'page' => 'jetpack#/newsletter' ) );
154 + }
155 + );
156 +
157 + // Track categories created through the category editor page
158 + add_action( 'wp_ajax_add-tag', array( $this, 'track_newsletter_category_creation' ), 1 );
159 +
160 + $newsletter_settings = new Newsletter_Settings();
161 + $newsletter_settings::init();
128 162 }
129 163
130 164 /**
131 165 * Jetpack_Subscriptions::xmlrpc_methods()
@@ -347,32 +381,14 @@
347 381 'discussion',
348 382 'stc_enabled'
349 383 );
350 384
351 - /** Enable Subscribe Modal */
352 -
353 - /** This filter is documented in plugins/jetpack/modules/subscriptions/subscribe-module/class-jetpack-subscribe-module.php */
354 - if ( apply_filters( 'jetpack_subscriptions_modal_enabled', false ) ) {
355 - add_settings_field(
356 - 'jetpack_subscriptions_comment_subscribe',
357 - __( 'Enable Subscribe Modal', 'jetpack' ),
358 - array( $this, 'subscribe_modal_setting' ),
359 - 'discussion',
360 - 'jetpack_subscriptions'
361 - );
362 -
363 - register_setting(
364 - 'discussion',
365 - 'sm_enabled'
366 - );
367 - }
368 -
369 - /** Email me whenever: Someone follows my blog */
385 + /** Email me whenever: Someone subscribes to my blog */
370 386 /* @since 8.1 */
371 387
372 388 add_settings_section(
373 389 'notifications_section',
374 - __( 'Someone follows my blog', 'jetpack' ),
390 + __( 'Someone subscribes to my blog', 'jetpack' ),
375 391 array( $this, 'social_notifications_subscribe_section' ),
376 392 'discussion'
377 393 );
378 394
@@ -388,39 +404,8 @@
388 404 'discussion',
389 405 'social_notifications_subscribe',
390 406 array( $this, 'social_notifications_subscribe_validate' )
391 407 );
392 -
393 - /** Subscription Messaging Options */
394 -
395 - register_setting(
396 - 'reading',
397 - 'subscription_options',
398 - array( $this, 'validate_settings' )
399 - );
400 -
401 - add_settings_section(
402 - 'email_settings',
403 - __( 'Follower Settings', 'jetpack' ),
404 - array( $this, 'reading_section' ),
405 - 'reading'
406 - );
407 -
408 - add_settings_field(
409 - 'invitation',
410 - __( 'Blog follow email text', 'jetpack' ),
411 - array( $this, 'setting_invitation' ),
412 - 'reading',
413 - 'email_settings'
414 - );
415 -
416 - add_settings_field(
417 - 'comment-follow',
418 - __( 'Comment follow email text', 'jetpack' ),
419 - array( $this, 'setting_comment_follow' ),
420 - 'reading',
421 - 'email_settings'
422 - );
423 408 }
424 409
425 410 /**
426 411 * Discussions setting section blurb.
@@ -479,25 +464,9 @@
479 464 <?php
480 465 }
481 466
482 467 /**
483 - * Subscribe Modal Toggle.
484 - */
485 - public function subscribe_modal_setting() {
486 -
487 - $sm_enabled = get_option( 'sm_enabled', 1 );
488 - ?>
489 -
490 - <p class="description">
491 - <input type="checkbox" name="sm_enabled" id="jetpack-subscribe-modal" value="1" <?php checked( $sm_enabled, 1 ); ?> />
492 - <?php esc_html_e( 'Show a popup subscribe modal to readers.', 'jetpack' ); ?>
493 - </p>
494 -
495 - <?php
496 - }
497 -
498 - /**
499 - * Someone follows my blog section
468 + * Someone subscribes to my blog section
500 469 *
501 470 * @since 8.1
502 471 */
503 472 public function social_notifications_subscribe_section() {
@@ -521,9 +490,9 @@
521 490 <?php
522 491 }
523 492
524 493 /**
525 - * Someone follows my blog Toggle
494 + * Someone subscribes to my blog Toggle
526 495 *
527 496 * @since 8.1
528 497 */
529 498 public function social_notifications_subscribe_field() {
@@ -533,9 +502,9 @@
533 502 <label>
534 503 <input type="checkbox" name="social_notifications_subscribe" id="social_notifications_subscribe" value="1" <?php checked( $checked ); ?> />
535 504 <?php
536 505 /* translators: this is a label for a setting that starts with "Email me whenever" */
537 - esc_html_e( 'Someone follows my blog', 'jetpack' );
506 + esc_html_e( 'Someone subscribes to my blog', 'jetpack' );
538 507 ?>
539 508 </label>
540 509 <?php
541 510 }
@@ -540,9 +509,9 @@
540 509 <?php
541 510 }
542 511
543 512 /**
544 - * Validate "Someone follows my blog" option
513 + * Validate "Someone subscribes to my blog" option
545 514 *
546 515 * @since 8.1
547 516 *
548 517 * @param String $input the input string to be validated.
@@ -558,81 +527,8 @@
558 527 return 'on';
559 528 }
560 529
561 530 /**
562 - * Validate settings for the Subscriptions module.
563 - *
564 - * @param array $settings Settings to be validated.
565 - */
566 - public function validate_settings( $settings ) {
567 - global $allowedposttags;
568 -
569 - $default = $this->get_default_settings();
570 -
571 - // Blog Follow.
572 - $settings['invitation'] = trim( wp_kses( $settings['invitation'], $allowedposttags ) );
573 - if ( empty( $settings['invitation'] ) ) {
574 - $settings['invitation'] = $default['invitation'];
575 - }
576 -
577 - // Comments Follow (single post).
578 - $settings['comment_follow'] = trim( wp_kses( $settings['comment_follow'], $allowedposttags ) );
579 - if ( empty( $settings['comment_follow'] ) ) {
580 - $settings['comment_follow'] = $default['comment_follow'];
581 - }
582 -
583 - return $settings;
584 - }
585 -
586 - /**
587 - * HTML output helper for Reading section.
588 - */
589 - public function reading_section() {
590 - echo '<p id="follower-settings">';
591 - esc_html_e( 'These settings change emails sent from your blog to followers.', 'jetpack' );
592 - echo '</p>';
593 - }
594 -
595 - /**
596 - * HTML output helper for Invitation section.
597 - */
598 - public function setting_invitation() {
599 - $settings = $this->get_settings();
600 - echo '<textarea name="subscription_options[invitation]" class="large-text" cols="50" rows="5">' . esc_textarea( $settings['invitation'] ) . '</textarea>';
601 - echo '<p><span class="description">' . esc_html__( 'Introduction text sent when someone follows your blog. (Site and confirmation details will be automatically added for you.)', 'jetpack' ) . '</span></p>';
602 - }
603 -
604 - /**
605 - * HTML output helper for Comment Follow section.
606 - */
607 - public function setting_comment_follow() {
608 - $settings = $this->get_settings();
609 - echo '<textarea name="subscription_options[comment_follow]" class="large-text" cols="50" rows="5">' . esc_textarea( $settings['comment_follow'] ) . '</textarea>';
610 - echo '<p><span class="description">' . esc_html__( 'Introduction text sent when someone follows a post on your blog. (Site and confirmation details will be automatically added for you.)', 'jetpack' ) . '</span></p>';
611 - }
612 -
613 - /**
614 - * Get default settings for the Subscriptions module.
615 - */
616 - public function get_default_settings() {
617 - $site_url = get_home_url();
618 - $display_url = preg_replace( '(^https?://)', '', untrailingslashit( $site_url ) );
619 -
620 - return array(
621 - /* translators: Both %1$s and %2$s is site address */
622 - 'invitation' => sprintf( __( "Howdy,\nYou recently subscribed to <a href='%1\$s'>%2\$s</a> and we need to verify the email you provided. Once you confirm below, you'll be able to receive and read new posts.\n\nIf you believe this is an error, ignore this message and nothing more will happen.", 'jetpack' ), $site_url, $display_url ),
623 - 'comment_follow' => __( "Howdy.\n\nYou recently followed one of my posts. This means you will receive an email when new comments are posted.\n\nTo activate, click confirm below. If you believe this is an error, ignore this message and we'll never bother you again.", 'jetpack' ),
624 - );
625 - }
626 -
627 - /**
628 - * Reeturn merged `subscription_options` option with module default settings.
629 - */
630 - public function get_settings() {
631 - return wp_parse_args( (array) get_option( 'subscription_options' ), $this->get_default_settings() );
632 - }
633 -
634 - /**
635 531 * Jetpack_Subscriptions::subscribe()
636 532 *
637 533 * Send a synchronous XML-RPC subscribe to blog posts or subscribe to post comments request.
638 534 *
@@ -671,8 +567,9 @@
671 567
672 568 if ( $async ) {
673 569 XMLRPC_Async_Call::add_call( 'jetpack.subscribeToSite', 0, $email, $post_id, serialize( $extra_data ) ); //phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
674 570 } else {
571 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false
675 572 $xml->addCall( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) ); //phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
676 573 }
677 574 }
678 575
@@ -680,19 +577,24 @@
680 577 return;
681 578 }
682 579
683 580 // Call.
581 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false, otherwise we return early
684 582 $xml->query();
685 583
584 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false, otherwise we return early
686 585 if ( $xml->isError() ) {
586 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false, otherwise we return early
687 587 return $xml->get_jetpack_error();
688 588 }
689 589
590 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false
690 591 $responses = $xml->getResponse();
691 592
692 593 $r = array();
693 594 foreach ( (array) $responses as $response ) {
694 595 if ( isset( $response['faultCode'] ) || isset( $response['faultString'] ) ) {
596 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false
695 597 $r[] = $xml->get_jetpack_error( $response['faultCode'], $response['faultString'] );
696 598 continue;
697 599 }
698 600
@@ -732,10 +634,10 @@
732 634 * When a user submits their email via the blog subscription widget, check the details and call the subsribe() method.
733 635 */
734 636 public function widget_submit() {
735 637 // Check the nonce.
736 - if ( is_user_logged_in() ) {
737 - check_admin_referer( 'blogsub_subscribe_' . get_current_blog_id() );
638 + if ( ! wp_verify_nonce( isset( $_REQUEST['_wpnonce'] ) ? sanitize_key( $_REQUEST['_wpnonce'] ) : '', 'blogsub_subscribe_' . \Jetpack_Options::get_option( 'id' ) ) ) {
639 + return false;
738 640 }
739 641
740 642 if ( empty( $_REQUEST['email'] ) || ! is_string( $_REQUEST['email'] ) ) {
741 643 return false;
@@ -810,9 +712,9 @@
810 712 */
811 713 do_action( 'jetpack_subscriptions_form_submission', $result );
812 714
813 715 wp_safe_redirect( "$redirect#$redirect_fragment" );
814 - exit;
716 + exit( 0 );
815 717 }
816 718
817 719 /**
818 720 * Jetpack_Subscriptions::comment_subscribe_init()
@@ -823,8 +725,13 @@
823 725 */
824 726 public function comment_subscribe_init( $submit_button ) {
825 727 global $post;
826 728
729 + // Subscriptions are only available for posts so far.
730 + if ( ! $post || 'post' !== $post->post_type ) {
731 + return $submit_button;
732 + }
733 +
827 734 $comments_checked = '';
828 735 $blog_checked = '';
829 736
830 737 // Check for a comment / blog submission and set a cookie to retain the setting and check the boxes.
@@ -903,8 +810,19 @@
903 810 * @param int|string $comment_id Comment thread being subscribed to.
904 811 * @param string $approved Comment status.
905 812 */
906 813 public function comment_subscribe_submit( $comment_id, $approved ) {
814 + /**
815 + * Filters whether to skip comment subscription processing.
816 + *
817 + * @since 15.5
818 + *
819 + * @param bool $skip Whether to skip comment subscription. Default false.
820 + */
821 + if ( apply_filters( 'jetpack_subscription_comment_subscribe_skip', false ) ) {
822 + return;
823 + }
824 +
907 825 if ( 'spam' === $approved ) {
908 826 return;
909 827 }
910 828
@@ -967,9 +885,9 @@
967 885 public function set_cookies( $subscribe_to_post = false, $post_id = null, $subscribe_to_blog = false ) {
968 886 $post_id = (int) $post_id;
969 887
970 888 /** This filter is already documented in core/wp-includes/comment-functions.php */
971 - $cookie_lifetime = apply_filters( 'comment_cookie_lifetime', 30000000 );
889 + $cookie_lifetime = apply_filters( 'comment_cookie_lifetime', YEAR_IN_SECONDS );
972 890
973 891 /**
974 892 * Filter the Jetpack Comment cookie path.
975 893 *
@@ -992,15 +910,15 @@
992 910 */
993 911 $cookie_domain = apply_filters( 'jetpack_comment_cookie_domain', COOKIE_DOMAIN );
994 912
995 913 if ( $subscribe_to_post && $post_id >= 0 ) {
996 - setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain, is_ssl(), true );
914 + setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, '1', time() + $cookie_lifetime, $cookie_path, $cookie_domain, is_ssl(), true );
997 915 } else {
998 916 setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, '', time() - 3600, $cookie_path, $cookie_domain, is_ssl(), true );
999 917 }
1000 918
1001 919 if ( $subscribe_to_blog ) {
1002 - setcookie( 'jetpack_blog_subscribe_' . self::$hash, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain, is_ssl(), true );
920 + setcookie( 'jetpack_blog_subscribe_' . self::$hash, '1', time() + $cookie_lifetime, $cookie_path, $cookie_domain, is_ssl(), true );
1003 921 } else {
1004 922 setcookie( 'jetpack_blog_subscribe_' . self::$hash, '', time() - 3600, $cookie_path, $cookie_domain, is_ssl(), true );
1005 923 }
1006 924 }
@@ -1018,8 +936,26 @@
1018 936 }
1019 937 }
1020 938
1021 939 /**
940 + * Set the featured image in email option to `1` when the Subscriptions module is activated in the first time.
941 + *
942 + * @return void
943 + */
944 + public function set_featured_image_in_email_default() {
945 + add_option( 'wpcom_featured_image_in_email', 1 );
946 + }
947 +
948 + /**
949 + * Set the email post to subscribers default option to `1` when the Subscriptions module is activated for the first time.
950 + *
951 + * @return void
952 + */
953 + public function set_newsletter_send_default() {
954 + add_option( 'wpcom_newsletter_send_default', 1 );
955 + }
956 +
957 + /**
1022 958 * Save a flag when a post was ever published.
1023 959 *
1024 960 * It saves the post meta when the post was published and becomes a draft.
1025 961 * Then this meta is used to hide subscription messaging in Publish panel.
@@ -1028,8 +964,13 @@
1028 964 * @param string $old_status The "old" post status of the transition when saved.
1029 965 * @param object $post obj The post object.
1030 966 */
1031 967 public function maybe_set_first_published_status( $new_status, $old_status, $post ) {
968 + // Subscriptions are only available for posts so far.
969 + if ( ! $post instanceof \WP_Post || 'post' !== $post->post_type ) {
970 + return;
971 + }
972 +
1032 973 $was_post_ever_published = get_post_meta( $post->ID, '_jetpack_post_was_ever_published', true );
1033 974 if ( ! $was_post_ever_published && 'publish' === $old_status && 'draft' === $new_status ) {
1034 975 update_post_meta( $post->ID, '_jetpack_post_was_ever_published', true );
1035 976 }
@@ -1035,14 +976,24 @@
1035 976 }
1036 977 }
1037 978
1038 979 /**
1039 - * Checks if the current user can publish posts.
980 + * Checks if the current user can edit posts.
1040 981 *
1041 982 * @return bool
1042 983 */
1043 984 public function first_published_status_meta_auth_callback() {
1044 - if ( current_user_can( 'publish_posts' ) ) {
985 + /**
986 + * Filter the capability required to edit the "was ever published" post meta.
987 + *
988 + * @module subscriptions
989 + *
990 + * @since 13.4
991 + *
992 + * @param string $capability User capability needed to edit the "was ever published" meta. Default to edit_posts.
993 + */
994 + $capability = apply_filters( 'jetpack_subscriptions_post_was_ever_published_capability', 'edit_posts' );
995 + if ( current_user_can( $capability ) ) {
1045 996 return true;
1046 997 }
1047 998 return false;
1048 999 }
@@ -1051,21 +1002,121 @@
1051 1002 * Registers the 'post_was_ever_published' post meta for use in the REST API.
1052 1003 */
1053 1004 public function register_post_meta() {
1054 1005 $jetpack_post_was_ever_published = array(
1055 - 'type' => 'boolean',
1056 - 'description' => __( 'Whether the post was ever published.', 'jetpack' ),
1057 - 'single' => true,
1058 - 'default' => false,
1059 - 'show_in_rest' => array(
1006 + 'type' => 'boolean',
1007 + 'description' => __( 'Whether the post was ever published.', 'jetpack' ),
1008 + 'single' => true,
1009 + 'default' => false,
1010 + 'show_in_rest' => array(
1060 1011 'name' => 'jetpack_post_was_ever_published',
1061 1012 ),
1062 - 'auth_callback' => array( $this, 'first_published_status_meta_auth_callback' ),
1013 + 'auth_callback' => array( $this, 'first_published_status_meta_auth_callback' ),
1014 + 'object_subtype' => 'post', // Subscriptions are only for the post post type so far, so we can limit this meta to posts only.
1063 1015 );
1064 1016
1065 1017 register_meta( 'post', '_jetpack_post_was_ever_published', $jetpack_post_was_ever_published );
1066 1018 }
1067 1019
1020 + /**
1021 + * Create a Subscribers menu displayed on self-hosted sites.
1022 + *
1023 + * - It is not displayed on WordPress.com sites.
1024 + * - It directs you to Calypso to the existing Subscribers page.
1025 + * - It is retired once the Newsletter modernization filter is on, since the
1026 + * unified Newsletter page then owns the Subscribers tab.
1027 + *
1028 + * @return void
1029 + */
1030 + public function add_subscribers_menu() {
1031 + /*
1032 + * Referenced as a string literal (mirrors Newsletter\Settings::MODERNIZATION_FILTER)
1033 + * to keep this bootstrap path safe if the packaged Newsletter Settings class does
1034 + * not expose the constant yet.
1035 + */
1036 + if ( apply_filters( 'rsm_jetpack_ui_modernization_newsletter', true ) ) {
1037 + return;
1038 + }
1039 +
1040 + /*
1041 + * Do not display any menu on WoA and WordPress.com Simple sites (unless Classic wp-admin is enabled).
1042 + * They already get a menu item under Users via nav-unification.
1043 + */
1044 + if ( ( new Host() )->is_wpcom_platform() && get_option( 'wpcom_admin_interface' ) !== 'wp-admin' ) {
1045 + return;
1046 + }
1047 +
1048 + $status = new Status();
1049 +
1050 + /*
1051 + * Do not display if we're in Offline mode,
1052 + * or if the user is not connected.
1053 + */
1054 + if (
1055 + $status->is_offline_mode()
1056 + || ! ( new Connection_Manager( 'jetpack' ) )->is_user_connected()
1057 + ) {
1058 + return;
1059 + }
1060 +
1061 + /**
1062 + * Enables the new in development subscribers in wp-admin dashboard.
1063 + *
1064 + * @since 9.5.0
1065 + *
1066 + * @param bool If the new dashboard is enabled. Defaults on for every site; hosts
1067 + * can opt out with this filter.
1068 + */
1069 + if ( apply_filters( 'jetpack_wp_admin_subscriber_management_enabled', true ) ) {
1070 + return;
1071 + }
1072 +
1073 + $blog_id = Connection_Manager::get_site_id( true );
1074 +
1075 + $link = Redirect::get_url(
1076 + 'jetpack-menu-jetpack-manage-subscribers',
1077 + array( 'site' => $blog_id ? $blog_id : $status->get_site_suffix() )
1078 + );
1079 +
1080 + Admin_Menu::add_menu(
1081 + __( 'Subscribers', 'jetpack' ),
1082 + __( 'Subscribers', 'jetpack' ) . ' <span aria-hidden="true">↗</span>',
1083 + 'manage_options',
1084 + esc_url( $link ),
1085 + null,
1086 + 100
1087 + );
1088 + }
1089 +
1090 + /**
1091 + * Record tracks event if categories is created when user enters
1092 + * the edit category page through the newsletter settings page.
1093 + *
1094 + * @return void
1095 + */
1096 + public function track_newsletter_category_creation() {
1097 +
1098 + // phpcs:disable WordPress.Security.NonceVerification.Missing
1099 + if ( empty( $_POST['_wp_http_referer'] ) ) {
1100 + return;
1101 + }
1102 +
1103 + if ( strpos( sanitize_url( wp_unslash( $_POST['_wp_http_referer'] ) ), 'referer=newsletter-categories' ) > -1 ) {
1104 +
1105 + $parent = filter_var( empty( $_POST['parent'] ) ? 0 : wp_unslash( $_POST['parent'] ), FILTER_SANITIZE_NUMBER_INT );
1106 +
1107 + $is_child_category = $parent > 0;
1108 +
1109 + $tracking = new Automattic\Jetpack\Tracking();
1110 + $tracking->tracks_record_event(
1111 + wp_get_current_user(),
1112 + 'jetpack_newsletter_add_category',
1113 + array(
1114 + 'is_child_category' => $is_child_category,
1115 + )
1116 + );
1117 + }
1118 + }
1068 1119 }
1069 1120
1070 1121 Jetpack_Subscriptions::init();
1071 1122
@@ -1070,4 +1121,10 @@
1070 1121 Jetpack_Subscriptions::init();
1071 1122
1072 1123 require __DIR__ . '/subscriptions/views.php';
1073 1124 require __DIR__ . '/subscriptions/subscribe-modal/class-jetpack-subscribe-modal.php';
1125 +require __DIR__ . '/subscriptions/subscribe-overlay/class-jetpack-subscribe-overlay.php';
1126 +require __DIR__ . '/subscriptions/subscribe-floating-button/class-jetpack-subscribe-floating-button.php';
1127 +require __DIR__ . '/subscriptions/newsletter-widget/class-jetpack-newsletter-dashboard-widget.php';
1128 +
1129 +require_once __DIR__ . '/subscriptions/abilities/class-newsletter-abilities.php';
1130 +\Automattic\Jetpack\Plugin\Abilities\Newsletter_Abilities::init();