PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-beta
Jetpack – WP Security, Backup, Speed, & Growth v16.3-beta
16.3-beta 16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 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 All 507 releases
← All changes | modules/subscriptions.php +225 -163 12.4.2 → 16.3-beta View file →
@@ -1,25 +1,39 @@
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\Newsletter\Urls as Newsletter_Urls;
23 +use Automattic\Jetpack\Redirect;
24 +use Automattic\Jetpack\Status;
25 +use Automattic\Jetpack\Status\Host;
19 26
27 +if ( ! defined( 'ABSPATH' ) ) {
28 + exit( 0 );
29 +}
30 +
20 31 add_action( 'jetpack_modules_loaded', 'jetpack_subscriptions_load' );
21 32
33 +// Loads the User Content Link Redirection feature.
34 +require_once __DIR__ . '/subscriptions/jetpack-user-content-link-redirection.php';
35 +
22 36 /**
23 37 * Loads the Subscriptions module.
24 38 */
25 39 function jetpack_subscriptions_load() {
@@ -36,13 +50,13 @@
36 50 function jetpack_subscriptions_cherry_pick_server_data() {
37 51 $data = array();
38 52
39 53 foreach ( $_SERVER as $key => $value ) {
40 - if ( ! is_string( $value ) || 0 === strpos( $key, 'HTTP_COOKIE' ) ) {
54 + if ( ! is_string( $value ) || str_starts_with( $key, 'HTTP_COOKIE' ) ) {
41 55 continue;
42 56 }
43 57
44 - if ( 0 === strpos( $key, 'HTTP_' ) || in_array( $key, array( 'REMOTE_ADDR', 'REQUEST_URI', 'DOCUMENT_URI' ), true ) ) {
58 + if ( str_starts_with( $key, 'HTTP_' ) || in_array( $key, array( 'REMOTE_ADDR', 'REQUEST_URI', 'DOCUMENT_URI' ), true ) ) {
45 59 $data[ $key ] = $value;
46 60 }
47 61 }
48 62
@@ -50,8 +64,10 @@
50 64 }
51 65
52 66 /**
53 67 * Main class file for the Subscriptions module.
68 + *
69 + * @phan-constructor-used-for-side-effects
54 70 */
55 71 class Jetpack_Subscriptions {
56 72 /**
57 73 * Whether Jetpack has been instantiated or not.
@@ -120,12 +136,31 @@
120 136 add_filter( 'post_updated_messages', array( $this, 'update_published_message' ), 18, 1 );
121 137
122 138 // Set "social_notifications_subscribe" option during the first-time activation.
123 139 add_action( 'jetpack_activate_module_subscriptions', array( $this, 'set_social_notifications_subscribe' ) );
140 + add_action( 'jetpack_activate_module_subscriptions', array( $this, 'set_featured_image_in_email_default' ) );
141 + add_action( 'jetpack_activate_module_subscriptions', array( $this, 'set_newsletter_send_default' ) );
124 142
125 143 // Hide subscription messaging in Publish panel for posts that were published in the past
126 144 add_action( 'init', array( $this, 'register_post_meta' ), 20 );
127 145 add_action( 'transition_post_status', array( $this, 'maybe_set_first_published_status' ), 10, 3 );
146 +
147 + // Add Subscribers menu to Jetpack navigation.
148 + add_action( 'jetpack_admin_menu', array( $this, 'add_subscribers_menu' ) );
149 +
150 + // Customize the configuration URL to lead to the Subscriptions settings.
151 + add_filter(
152 + 'jetpack_module_configuration_url_subscriptions',
153 + function () {
154 + return Newsletter_Urls::get_newsletter_settings_url();
155 + }
156 + );
157 +
158 + // Track categories created through the category editor page
159 + add_action( 'wp_ajax_add-tag', array( $this, 'track_newsletter_category_creation' ), 1 );
160 +
161 + $newsletter_settings = new Newsletter_Settings();
162 + $newsletter_settings::init();
128 163 }
129 164
130 165 /**
131 166 * Jetpack_Subscriptions::xmlrpc_methods()
@@ -347,32 +382,14 @@
347 382 'discussion',
348 383 'stc_enabled'
349 384 );
350 385
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 */
386 + /** Email me whenever: Someone subscribes to my blog */
370 387 /* @since 8.1 */
371 388
372 389 add_settings_section(
373 390 'notifications_section',
374 - __( 'Someone follows my blog', 'jetpack' ),
391 + __( 'Someone subscribes to my blog', 'jetpack' ),
375 392 array( $this, 'social_notifications_subscribe_section' ),
376 393 'discussion'
377 394 );
378 395
@@ -388,39 +405,8 @@
388 405 'discussion',
389 406 'social_notifications_subscribe',
390 407 array( $this, 'social_notifications_subscribe_validate' )
391 408 );
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 409 }
424 410
425 411 /**
426 412 * Discussions setting section blurb.
@@ -479,25 +465,9 @@
479 465 <?php
480 466 }
481 467
482 468 /**
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
469 + * Someone subscribes to my blog section
500 470 *
501 471 * @since 8.1
502 472 */
503 473 public function social_notifications_subscribe_section() {
@@ -521,9 +491,9 @@
521 491 <?php
522 492 }
523 493
524 494 /**
525 - * Someone follows my blog Toggle
495 + * Someone subscribes to my blog Toggle
526 496 *
527 497 * @since 8.1
528 498 */
529 499 public function social_notifications_subscribe_field() {
@@ -533,9 +503,9 @@
533 503 <label>
534 504 <input type="checkbox" name="social_notifications_subscribe" id="social_notifications_subscribe" value="1" <?php checked( $checked ); ?> />
535 505 <?php
536 506 /* translators: this is a label for a setting that starts with "Email me whenever" */
537 - esc_html_e( 'Someone follows my blog', 'jetpack' );
507 + esc_html_e( 'Someone subscribes to my blog', 'jetpack' );
538 508 ?>
539 509 </label>
540 510 <?php
541 511 }
@@ -540,9 +510,9 @@
540 510 <?php
541 511 }
542 512
543 513 /**
544 - * Validate "Someone follows my blog" option
514 + * Validate "Someone subscribes to my blog" option
545 515 *
546 516 * @since 8.1
547 517 *
548 518 * @param String $input the input string to be validated.
@@ -558,81 +528,8 @@
558 528 return 'on';
559 529 }
560 530
561 531 /**
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 532 * Jetpack_Subscriptions::subscribe()
636 533 *
637 534 * Send a synchronous XML-RPC subscribe to blog posts or subscribe to post comments request.
638 535 *
@@ -671,8 +568,9 @@
671 568
672 569 if ( $async ) {
673 570 XMLRPC_Async_Call::add_call( 'jetpack.subscribeToSite', 0, $email, $post_id, serialize( $extra_data ) ); //phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
674 571 } else {
572 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false
675 573 $xml->addCall( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) ); //phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
676 574 }
677 575 }
678 576
@@ -680,19 +578,24 @@
680 578 return;
681 579 }
682 580
683 581 // Call.
582 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false, otherwise we return early
684 583 $xml->query();
685 584
585 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false, otherwise we return early
686 586 if ( $xml->isError() ) {
587 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false, otherwise we return early
687 588 return $xml->get_jetpack_error();
688 589 }
689 590
591 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false
690 592 $responses = $xml->getResponse();
691 593
692 594 $r = array();
693 595 foreach ( (array) $responses as $response ) {
694 596 if ( isset( $response['faultCode'] ) || isset( $response['faultString'] ) ) {
597 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false
695 598 $r[] = $xml->get_jetpack_error( $response['faultCode'], $response['faultString'] );
696 599 continue;
697 600 }
698 601
@@ -732,10 +635,10 @@
732 635 * When a user submits their email via the blog subscription widget, check the details and call the subsribe() method.
733 636 */
734 637 public function widget_submit() {
735 638 // Check the nonce.
736 - if ( is_user_logged_in() ) {
737 - check_admin_referer( 'blogsub_subscribe_' . get_current_blog_id() );
639 + if ( ! wp_verify_nonce( isset( $_REQUEST['_wpnonce'] ) ? sanitize_key( $_REQUEST['_wpnonce'] ) : '', 'blogsub_subscribe_' . \Jetpack_Options::get_option( 'id' ) ) ) {
640 + return false;
738 641 }
739 642
740 643 if ( empty( $_REQUEST['email'] ) || ! is_string( $_REQUEST['email'] ) ) {
741 644 return false;
@@ -810,9 +713,9 @@
810 713 */
811 714 do_action( 'jetpack_subscriptions_form_submission', $result );
812 715
813 716 wp_safe_redirect( "$redirect#$redirect_fragment" );
814 - exit;
717 + exit( 0 );
815 718 }
816 719
817 720 /**
818 721 * Jetpack_Subscriptions::comment_subscribe_init()
@@ -823,8 +726,13 @@
823 726 */
824 727 public function comment_subscribe_init( $submit_button ) {
825 728 global $post;
826 729
730 + // Subscriptions are only available for posts so far.
731 + if ( ! $post || 'post' !== $post->post_type ) {
732 + return $submit_button;
733 + }
734 +
827 735 $comments_checked = '';
828 736 $blog_checked = '';
829 737
830 738 // Check for a comment / blog submission and set a cookie to retain the setting and check the boxes.
@@ -903,8 +811,19 @@
903 811 * @param int|string $comment_id Comment thread being subscribed to.
904 812 * @param string $approved Comment status.
905 813 */
906 814 public function comment_subscribe_submit( $comment_id, $approved ) {
815 + /**
816 + * Filters whether to skip comment subscription processing.
817 + *
818 + * @since 15.5
819 + *
820 + * @param bool $skip Whether to skip comment subscription. Default false.
821 + */
822 + if ( apply_filters( 'jetpack_subscription_comment_subscribe_skip', false ) ) {
823 + return;
824 + }
825 +
907 826 if ( 'spam' === $approved ) {
908 827 return;
909 828 }
910 829
@@ -967,9 +886,9 @@
967 886 public function set_cookies( $subscribe_to_post = false, $post_id = null, $subscribe_to_blog = false ) {
968 887 $post_id = (int) $post_id;
969 888
970 889 /** This filter is already documented in core/wp-includes/comment-functions.php */
971 - $cookie_lifetime = apply_filters( 'comment_cookie_lifetime', 30000000 );
890 + $cookie_lifetime = apply_filters( 'comment_cookie_lifetime', YEAR_IN_SECONDS );
972 891
973 892 /**
974 893 * Filter the Jetpack Comment cookie path.
975 894 *
@@ -992,15 +911,15 @@
992 911 */
993 912 $cookie_domain = apply_filters( 'jetpack_comment_cookie_domain', COOKIE_DOMAIN );
994 913
995 914 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 );
915 + setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, '1', time() + $cookie_lifetime, $cookie_path, $cookie_domain, is_ssl(), true );
997 916 } else {
998 917 setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, '', time() - 3600, $cookie_path, $cookie_domain, is_ssl(), true );
999 918 }
1000 919
1001 920 if ( $subscribe_to_blog ) {
1002 - setcookie( 'jetpack_blog_subscribe_' . self::$hash, 1, time() + $cookie_lifetime, $cookie_path, $cookie_domain, is_ssl(), true );
921 + setcookie( 'jetpack_blog_subscribe_' . self::$hash, '1', time() + $cookie_lifetime, $cookie_path, $cookie_domain, is_ssl(), true );
1003 922 } else {
1004 923 setcookie( 'jetpack_blog_subscribe_' . self::$hash, '', time() - 3600, $cookie_path, $cookie_domain, is_ssl(), true );
1005 924 }
1006 925 }
@@ -1018,8 +937,26 @@
1018 937 }
1019 938 }
1020 939
1021 940 /**
941 + * Set the featured image in email option to `1` when the Subscriptions module is activated in the first time.
942 + *
943 + * @return void
944 + */
945 + public function set_featured_image_in_email_default() {
946 + add_option( 'wpcom_featured_image_in_email', 1 );
947 + }
948 +
949 + /**
950 + * Set the email post to subscribers default option to `1` when the Subscriptions module is activated for the first time.
951 + *
952 + * @return void
953 + */
954 + public function set_newsletter_send_default() {
955 + add_option( 'wpcom_newsletter_send_default', 1 );
956 + }
957 +
958 + /**
1022 959 * Save a flag when a post was ever published.
1023 960 *
1024 961 * It saves the post meta when the post was published and becomes a draft.
1025 962 * Then this meta is used to hide subscription messaging in Publish panel.
@@ -1028,8 +965,13 @@
1028 965 * @param string $old_status The "old" post status of the transition when saved.
1029 966 * @param object $post obj The post object.
1030 967 */
1031 968 public function maybe_set_first_published_status( $new_status, $old_status, $post ) {
969 + // Subscriptions are only available for posts so far.
970 + if ( ! $post instanceof \WP_Post || 'post' !== $post->post_type ) {
971 + return;
972 + }
973 +
1032 974 $was_post_ever_published = get_post_meta( $post->ID, '_jetpack_post_was_ever_published', true );
1033 975 if ( ! $was_post_ever_published && 'publish' === $old_status && 'draft' === $new_status ) {
1034 976 update_post_meta( $post->ID, '_jetpack_post_was_ever_published', true );
1035 977 }
@@ -1035,14 +977,24 @@
1035 977 }
1036 978 }
1037 979
1038 980 /**
1039 - * Checks if the current user can publish posts.
981 + * Checks if the current user can edit posts.
1040 982 *
1041 983 * @return bool
1042 984 */
1043 985 public function first_published_status_meta_auth_callback() {
1044 - if ( current_user_can( 'publish_posts' ) ) {
986 + /**
987 + * Filter the capability required to edit the "was ever published" post meta.
988 + *
989 + * @module subscriptions
990 + *
991 + * @since 13.4
992 + *
993 + * @param string $capability User capability needed to edit the "was ever published" meta. Default to edit_posts.
994 + */
995 + $capability = apply_filters( 'jetpack_subscriptions_post_was_ever_published_capability', 'edit_posts' );
996 + if ( current_user_can( $capability ) ) {
1045 997 return true;
1046 998 }
1047 999 return false;
1048 1000 }
@@ -1051,21 +1003,124 @@
1051 1003 * Registers the 'post_was_ever_published' post meta for use in the REST API.
1052 1004 */
1053 1005 public function register_post_meta() {
1054 1006 $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(
1007 + 'type' => 'boolean',
1008 + 'description' => __( 'Whether the post was ever published.', 'jetpack' ),
1009 + 'single' => true,
1010 + 'default' => false,
1011 + 'show_in_rest' => array(
1060 1012 'name' => 'jetpack_post_was_ever_published',
1061 1013 ),
1062 - 'auth_callback' => array( $this, 'first_published_status_meta_auth_callback' ),
1014 + 'auth_callback' => array( $this, 'first_published_status_meta_auth_callback' ),
1015 + 'object_subtype' => 'post', // Subscriptions are only for the post post type so far, so we can limit this meta to posts only.
1063 1016 );
1064 1017
1065 1018 register_meta( 'post', '_jetpack_post_was_ever_published', $jetpack_post_was_ever_published );
1066 1019 }
1067 1020
1021 + /**
1022 + * Create a Subscribers menu displayed on self-hosted sites.
1023 + *
1024 + * - It is not displayed on WordPress.com sites.
1025 + * - It directs you to Calypso to the existing Subscribers page.
1026 + * - It is retired once the Newsletter modernization filter is on, since the
1027 + * unified Newsletter page then owns the Subscribers tab.
1028 + *
1029 + * @return void
1030 + */
1031 + public function add_subscribers_menu() {
1032 + /*
1033 + * Referenced as a string literal (mirrors Newsletter\Settings::MODERNIZATION_FILTER)
1034 + * to keep this bootstrap path safe if the packaged Newsletter Settings class does
1035 + * not expose the constant yet.
1036 + */
1037 + if ( apply_filters( 'rsm_jetpack_ui_modernization_newsletter', true ) ) {
1038 + return;
1039 + }
1040 +
1041 + /*
1042 + * Do not display any menu on WoA and WordPress.com Simple sites (unless Classic wp-admin is enabled).
1043 + * They already get a menu item under Users via nav-unification.
1044 + */
1045 + if ( ( new Host() )->is_wpcom_platform() && get_option( 'wpcom_admin_interface' ) !== 'wp-admin' ) {
1046 + return;
1047 + }
1048 +
1049 + $status = new Status();
1050 +
1051 + /*
1052 + * Do not display if we're in Offline mode,
1053 + * or if the user is not connected.
1054 + */
1055 + if (
1056 + $status->is_offline_mode()
1057 + || ! ( new Connection_Manager( 'jetpack' ) )->is_user_connected()
1058 + ) {
1059 + return;
1060 + }
1061 +
1062 + /**
1063 + * Enables the new in development subscribers in wp-admin dashboard.
1064 + *
1065 + * @since 9.5.0
1066 + *
1067 + * @param bool If the new dashboard is enabled. Defaults on for every site; hosts
1068 + * can opt out with this filter.
1069 + */
1070 + if ( apply_filters( 'jetpack_wp_admin_subscriber_management_enabled', true ) ) {
1071 + return;
1072 + }
1073 +
1074 + $blog_id = Connection_Manager::get_site_id( true );
1075 +
1076 + $link = Redirect::get_url(
1077 + 'jetpack-menu-jetpack-manage-subscribers',
1078 + array( 'site' => $blog_id ? $blog_id : $status->get_site_suffix() )
1079 + );
1080 +
1081 + $position = defined( Admin_Menu::class . '::POSITION_EXTERNAL' ) ? Admin_Menu::POSITION_EXTERNAL : 100;
1082 +
1083 + Admin_Menu::add_menu(
1084 + __( 'Subscribers', 'jetpack' ),
1085 + __( 'Subscribers', 'jetpack' ) . ' <span aria-hidden="true">↗</span>',
1086 + 'manage_options',
1087 + esc_url( $link ),
1088 + null,
1089 + $position,
1090 + array( 'key' => 'jetpack-subscribers' )
1091 + );
1092 + }
1093 +
1094 + /**
1095 + * Record tracks event if categories is created when user enters
1096 + * the edit category page through the newsletter settings page.
1097 + *
1098 + * @return void
1099 + */
1100 + public function track_newsletter_category_creation() {
1101 +
1102 + // phpcs:disable WordPress.Security.NonceVerification.Missing
1103 + if ( empty( $_POST['_wp_http_referer'] ) ) {
1104 + return;
1105 + }
1106 +
1107 + if ( strpos( sanitize_url( wp_unslash( $_POST['_wp_http_referer'] ) ), 'referer=newsletter-categories' ) > -1 ) {
1108 +
1109 + $parent = filter_var( empty( $_POST['parent'] ) ? 0 : wp_unslash( $_POST['parent'] ), FILTER_SANITIZE_NUMBER_INT );
1110 +
1111 + $is_child_category = $parent > 0;
1112 +
1113 + $tracking = new Automattic\Jetpack\Tracking();
1114 + $tracking->tracks_record_event(
1115 + wp_get_current_user(),
1116 + 'jetpack_newsletter_add_category',
1117 + array(
1118 + 'is_child_category' => $is_child_category,
1119 + )
1120 + );
1121 + }
1122 + }
1068 1123 }
1069 1124
1070 1125 Jetpack_Subscriptions::init();
1071 1126
@@ -1070,4 +1125,11 @@
1070 1125 Jetpack_Subscriptions::init();
1071 1126
1072 1127 require __DIR__ . '/subscriptions/views.php';
1073 1128 require __DIR__ . '/subscriptions/subscribe-modal/class-jetpack-subscribe-modal.php';
1129 +require __DIR__ . '/subscriptions/subscribe-overlay/class-jetpack-subscribe-overlay.php';
1130 +require __DIR__ . '/subscriptions/subscribe-floating-button/class-jetpack-subscribe-floating-button.php';
1131 +require __DIR__ . '/subscriptions/newsletter-widget/class-jetpack-newsletter-dashboard-widget.php';
1132 +require_once __DIR__ . '/subscriptions/email-design-editor/class-jetpack-email-design-editor.php';
1133 +
1134 +require_once __DIR__ . '/subscriptions/abilities/class-newsletter-abilities.php';
1135 +\Automattic\Jetpack\Plugin\Abilities\Newsletter_Abilities::init();