PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.2
Jetpack – WP Security, Backup, Speed, & Growth v16.2
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 13.8.3 13.9.2 14.0.1 14.1.1 All 503 releases
← All changes | modules/subscriptions.php +175 -172 12.7.316.2 View file →
@@ -1,27 +1,33 @@
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;
18 19 use Automattic\Jetpack\Connection\Manager as Connection_Manager;
19 20 use Automattic\Jetpack\Connection\XMLRPC_Async_Call;
21 +use Automattic\Jetpack\Newsletter\Settings as Newsletter_Settings;
20 22 use Automattic\Jetpack\Redirect;
21 23 use Automattic\Jetpack\Status;
22 24 use Automattic\Jetpack\Status\Host;
23 25
26 +if ( ! defined( 'ABSPATH' ) ) {
27 + exit( 0 );
28 +}
29 +
24 30 add_action( 'jetpack_modules_loaded', 'jetpack_subscriptions_load' );
25 31
26 32 // Loads the User Content Link Redirection feature.
27 33 require_once __DIR__ . '/subscriptions/jetpack-user-content-link-redirection.php';
@@ -43,13 +49,13 @@
43 49 function jetpack_subscriptions_cherry_pick_server_data() {
44 50 $data = array();
45 51
46 52 foreach ( $_SERVER as $key => $value ) {
47 - if ( ! is_string( $value ) || 0 === strpos( $key, 'HTTP_COOKIE' ) ) {
53 + if ( ! is_string( $value ) || str_starts_with( $key, 'HTTP_COOKIE' ) ) {
48 54 continue;
49 55 }
50 56
51 - 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 ) ) {
52 58 $data[ $key ] = $value;
53 59 }
54 60 }
55 61
@@ -57,8 +63,10 @@
57 63 }
58 64
59 65 /**
60 66 * Main class file for the Subscriptions module.
67 + *
68 + * @phan-constructor-used-for-side-effects
61 69 */
62 70 class Jetpack_Subscriptions {
63 71 /**
64 72 * Whether Jetpack has been instantiated or not.
@@ -127,8 +135,10 @@
127 135 add_filter( 'post_updated_messages', array( $this, 'update_published_message' ), 18, 1 );
128 136
129 137 // Set "social_notifications_subscribe" option during the first-time activation.
130 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' ) );
131 141
132 142 // Hide subscription messaging in Publish panel for posts that were published in the past
133 143 add_action( 'init', array( $this, 'register_post_meta' ), 20 );
134 144 add_action( 'transition_post_status', array( $this, 'maybe_set_first_published_status' ), 10, 3 );
@@ -134,8 +144,22 @@
134 144 add_action( 'transition_post_status', array( $this, 'maybe_set_first_published_status' ), 10, 3 );
135 145
136 146 // Add Subscribers menu to Jetpack navigation.
137 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();
138 162 }
139 163
140 164 /**
141 165 * Jetpack_Subscriptions::xmlrpc_methods()
@@ -357,32 +381,14 @@
357 381 'discussion',
358 382 'stc_enabled'
359 383 );
360 384
361 - /** Enable Subscribe Modal */
362 -
363 - /** This filter is documented in plugins/jetpack/modules/subscriptions/subscribe-module/class-jetpack-subscribe-module.php */
364 - if ( apply_filters( 'jetpack_subscriptions_modal_enabled', false ) ) {
365 - add_settings_field(
366 - 'jetpack_subscriptions_comment_subscribe',
367 - __( 'Enable Subscribe Modal', 'jetpack' ),
368 - array( $this, 'subscribe_modal_setting' ),
369 - 'discussion',
370 - 'jetpack_subscriptions'
371 - );
372 -
373 - register_setting(
374 - 'discussion',
375 - 'sm_enabled'
376 - );
377 - }
378 -
379 - /** Email me whenever: Someone follows my blog */
385 + /** Email me whenever: Someone subscribes to my blog */
380 386 /* @since 8.1 */
381 387
382 388 add_settings_section(
383 389 'notifications_section',
384 - __( 'Someone follows my blog', 'jetpack' ),
390 + __( 'Someone subscribes to my blog', 'jetpack' ),
385 391 array( $this, 'social_notifications_subscribe_section' ),
386 392 'discussion'
387 393 );
388 394
@@ -398,39 +404,8 @@
398 404 'discussion',
399 405 'social_notifications_subscribe',
400 406 array( $this, 'social_notifications_subscribe_validate' )
401 407 );
402 -
403 - /** Subscription Messaging Options */
404 -
405 - register_setting(
406 - 'reading',
407 - 'subscription_options',
408 - array( $this, 'validate_settings' )
409 - );
410 -
411 - add_settings_section(
412 - 'email_settings',
413 - __( 'Follower Settings', 'jetpack' ),
414 - array( $this, 'reading_section' ),
415 - 'reading'
416 - );
417 -
418 - add_settings_field(
419 - 'invitation',
420 - __( 'Blog follow email text', 'jetpack' ),
421 - array( $this, 'setting_invitation' ),
422 - 'reading',
423 - 'email_settings'
424 - );
425 -
426 - add_settings_field(
427 - 'comment-follow',
428 - __( 'Comment follow email text', 'jetpack' ),
429 - array( $this, 'setting_comment_follow' ),
430 - 'reading',
431 - 'email_settings'
432 - );
433 408 }
434 409
435 410 /**
436 411 * Discussions setting section blurb.
@@ -489,25 +464,9 @@
489 464 <?php
490 465 }
491 466
492 467 /**
493 - * Subscribe Modal Toggle.
494 - */
495 - public function subscribe_modal_setting() {
496 -
497 - $sm_enabled = get_option( 'sm_enabled', 1 );
498 - ?>
499 -
500 - <p class="description">
501 - <input type="checkbox" name="sm_enabled" id="jetpack-subscribe-modal" value="1" <?php checked( $sm_enabled, 1 ); ?> />
502 - <?php esc_html_e( 'Show a popup subscribe modal to readers.', 'jetpack' ); ?>
503 - </p>
504 -
505 - <?php
506 - }
507 -
508 - /**
509 - * Someone follows my blog section
468 + * Someone subscribes to my blog section
510 469 *
511 470 * @since 8.1
512 471 */
513 472 public function social_notifications_subscribe_section() {
@@ -531,9 +490,9 @@
531 490 <?php
532 491 }
533 492
534 493 /**
535 - * Someone follows my blog Toggle
494 + * Someone subscribes to my blog Toggle
536 495 *
537 496 * @since 8.1
538 497 */
539 498 public function social_notifications_subscribe_field() {
@@ -543,9 +502,9 @@
543 502 <label>
544 503 <input type="checkbox" name="social_notifications_subscribe" id="social_notifications_subscribe" value="1" <?php checked( $checked ); ?> />
545 504 <?php
546 505 /* translators: this is a label for a setting that starts with "Email me whenever" */
547 - esc_html_e( 'Someone follows my blog', 'jetpack' );
506 + esc_html_e( 'Someone subscribes to my blog', 'jetpack' );
548 507 ?>
549 508 </label>
550 509 <?php
551 510 }
@@ -550,9 +509,9 @@
550 509 <?php
551 510 }
552 511
553 512 /**
554 - * Validate "Someone follows my blog" option
513 + * Validate "Someone subscribes to my blog" option
555 514 *
556 515 * @since 8.1
557 516 *
558 517 * @param String $input the input string to be validated.
@@ -568,81 +527,8 @@
568 527 return 'on';
569 528 }
570 529
571 530 /**
572 - * Validate settings for the Subscriptions module.
573 - *
574 - * @param array $settings Settings to be validated.
575 - */
576 - public function validate_settings( $settings ) {
577 - global $allowedposttags;
578 -
579 - $default = $this->get_default_settings();
580 -
581 - // Blog Follow.
582 - $settings['invitation'] = trim( wp_kses( $settings['invitation'], $allowedposttags ) );
583 - if ( empty( $settings['invitation'] ) ) {
584 - $settings['invitation'] = $default['invitation'];
585 - }
586 -
587 - // Comments Follow (single post).
588 - $settings['comment_follow'] = trim( wp_kses( $settings['comment_follow'], $allowedposttags ) );
589 - if ( empty( $settings['comment_follow'] ) ) {
590 - $settings['comment_follow'] = $default['comment_follow'];
591 - }
592 -
593 - return $settings;
594 - }
595 -
596 - /**
597 - * HTML output helper for Reading section.
598 - */
599 - public function reading_section() {
600 - echo '<p id="follower-settings">';
601 - esc_html_e( 'These settings change emails sent from your blog to followers.', 'jetpack' );
602 - echo '</p>';
603 - }
604 -
605 - /**
606 - * HTML output helper for Invitation section.
607 - */
608 - public function setting_invitation() {
609 - $settings = $this->get_settings();
610 - echo '<textarea name="subscription_options[invitation]" class="large-text" cols="50" rows="5">' . esc_textarea( $settings['invitation'] ) . '</textarea>';
611 - 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>';
612 - }
613 -
614 - /**
615 - * HTML output helper for Comment Follow section.
616 - */
617 - public function setting_comment_follow() {
618 - $settings = $this->get_settings();
619 - echo '<textarea name="subscription_options[comment_follow]" class="large-text" cols="50" rows="5">' . esc_textarea( $settings['comment_follow'] ) . '</textarea>';
620 - 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>';
621 - }
622 -
623 - /**
624 - * Get default settings for the Subscriptions module.
625 - */
626 - public function get_default_settings() {
627 - $site_url = get_home_url();
628 - $display_url = preg_replace( '(^https?://)', '', untrailingslashit( $site_url ) );
629 -
630 - return array(
631 - /* translators: Both %1$s and %2$s is site address */
632 - '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 ),
633 - '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' ),
634 - );
635 - }
636 -
637 - /**
638 - * Reeturn merged `subscription_options` option with module default settings.
639 - */
640 - public function get_settings() {
641 - return wp_parse_args( (array) get_option( 'subscription_options' ), $this->get_default_settings() );
642 - }
643 -
644 - /**
645 531 * Jetpack_Subscriptions::subscribe()
646 532 *
647 533 * Send a synchronous XML-RPC subscribe to blog posts or subscribe to post comments request.
648 534 *
@@ -681,8 +567,9 @@
681 567
682 568 if ( $async ) {
683 569 XMLRPC_Async_Call::add_call( 'jetpack.subscribeToSite', 0, $email, $post_id, serialize( $extra_data ) ); //phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
684 570 } else {
571 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false
685 572 $xml->addCall( 'jetpack.subscribeToSite', $email, $post_id, serialize( $extra_data ) ); //phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize
686 573 }
687 574 }
688 575
@@ -690,19 +577,24 @@
690 577 return;
691 578 }
692 579
693 580 // Call.
581 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false, otherwise we return early
694 582 $xml->query();
695 583
584 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false, otherwise we return early
696 585 if ( $xml->isError() ) {
586 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false, otherwise we return early
697 587 return $xml->get_jetpack_error();
698 588 }
699 589
590 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false
700 591 $responses = $xml->getResponse();
701 592
702 593 $r = array();
703 594 foreach ( (array) $responses as $response ) {
704 595 if ( isset( $response['faultCode'] ) || isset( $response['faultString'] ) ) {
596 + // @phan-suppress-next-line PhanPossiblyUndeclaredVariable -- $xml is set when $async is false
705 597 $r[] = $xml->get_jetpack_error( $response['faultCode'], $response['faultString'] );
706 598 continue;
707 599 }
708 600
@@ -742,10 +634,10 @@
742 634 * When a user submits their email via the blog subscription widget, check the details and call the subsribe() method.
743 635 */
744 636 public function widget_submit() {
745 637 // Check the nonce.
746 - if ( is_user_logged_in() ) {
747 - 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;
748 640 }
749 641
750 642 if ( empty( $_REQUEST['email'] ) || ! is_string( $_REQUEST['email'] ) ) {
751 643 return false;
@@ -820,9 +712,9 @@
820 712 */
821 713 do_action( 'jetpack_subscriptions_form_submission', $result );
822 714
823 715 wp_safe_redirect( "$redirect#$redirect_fragment" );
824 - exit;
716 + exit( 0 );
825 717 }
826 718
827 719 /**
828 720 * Jetpack_Subscriptions::comment_subscribe_init()
@@ -833,8 +725,13 @@
833 725 */
834 726 public function comment_subscribe_init( $submit_button ) {
835 727 global $post;
836 728
729 + // Subscriptions are only available for posts so far.
730 + if ( ! $post || 'post' !== $post->post_type ) {
731 + return $submit_button;
732 + }
733 +
837 734 $comments_checked = '';
838 735 $blog_checked = '';
839 736
840 737 // Check for a comment / blog submission and set a cookie to retain the setting and check the boxes.
@@ -913,8 +810,19 @@
913 810 * @param int|string $comment_id Comment thread being subscribed to.
914 811 * @param string $approved Comment status.
915 812 */
916 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 +
917 825 if ( 'spam' === $approved ) {
918 826 return;
919 827 }
920 828
@@ -977,9 +885,9 @@
977 885 public function set_cookies( $subscribe_to_post = false, $post_id = null, $subscribe_to_blog = false ) {
978 886 $post_id = (int) $post_id;
979 887
980 888 /** This filter is already documented in core/wp-includes/comment-functions.php */
981 - $cookie_lifetime = apply_filters( 'comment_cookie_lifetime', 30000000 );
889 + $cookie_lifetime = apply_filters( 'comment_cookie_lifetime', YEAR_IN_SECONDS );
982 890
983 891 /**
984 892 * Filter the Jetpack Comment cookie path.
985 893 *
@@ -1002,15 +910,15 @@
1002 910 */
1003 911 $cookie_domain = apply_filters( 'jetpack_comment_cookie_domain', COOKIE_DOMAIN );
1004 912
1005 913 if ( $subscribe_to_post && $post_id >= 0 ) {
1006 - 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 );
1007 915 } else {
1008 916 setcookie( 'jetpack_comments_subscribe_' . self::$hash . '_' . $post_id, '', time() - 3600, $cookie_path, $cookie_domain, is_ssl(), true );
1009 917 }
1010 918
1011 919 if ( $subscribe_to_blog ) {
1012 - 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 );
1013 921 } else {
1014 922 setcookie( 'jetpack_blog_subscribe_' . self::$hash, '', time() - 3600, $cookie_path, $cookie_domain, is_ssl(), true );
1015 923 }
1016 924 }
@@ -1028,8 +936,26 @@
1028 936 }
1029 937 }
1030 938
1031 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 + /**
1032 958 * Save a flag when a post was ever published.
1033 959 *
1034 960 * It saves the post meta when the post was published and becomes a draft.
1035 961 * Then this meta is used to hide subscription messaging in Publish panel.
@@ -1038,8 +964,13 @@
1038 964 * @param string $old_status The "old" post status of the transition when saved.
1039 965 * @param object $post obj The post object.
1040 966 */
1041 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 +
1042 973 $was_post_ever_published = get_post_meta( $post->ID, '_jetpack_post_was_ever_published', true );
1043 974 if ( ! $was_post_ever_published && 'publish' === $old_status && 'draft' === $new_status ) {
1044 975 update_post_meta( $post->ID, '_jetpack_post_was_ever_published', true );
1045 976 }
@@ -1045,14 +976,24 @@
1045 976 }
1046 977 }
1047 978
1048 979 /**
1049 - * Checks if the current user can publish posts.
980 + * Checks if the current user can edit posts.
1050 981 *
1051 982 * @return bool
1052 983 */
1053 984 public function first_published_status_meta_auth_callback() {
1054 - 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 ) ) {
1055 996 return true;
1056 997 }
1057 998 return false;
1058 999 }
@@ -1061,16 +1002,17 @@
1061 1002 * Registers the 'post_was_ever_published' post meta for use in the REST API.
1062 1003 */
1063 1004 public function register_post_meta() {
1064 1005 $jetpack_post_was_ever_published = array(
1065 - 'type' => 'boolean',
1066 - 'description' => __( 'Whether the post was ever published.', 'jetpack' ),
1067 - 'single' => true,
1068 - 'default' => false,
1069 - '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(
1070 1011 'name' => 'jetpack_post_was_ever_published',
1071 1012 ),
1072 - '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.
1073 1015 );
1074 1016
1075 1017 register_meta( 'post', '_jetpack_post_was_ever_published', $jetpack_post_was_ever_published );
1076 1018 }
@@ -1079,17 +1021,28 @@
1079 1021 * Create a Subscribers menu displayed on self-hosted sites.
1080 1022 *
1081 1023 * - It is not displayed on WordPress.com sites.
1082 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.
1083 1027 *
1084 1028 * @return void
1085 1029 */
1086 1030 public function add_subscribers_menu() {
1087 1031 /*
1088 - * Do not display any menu on WoA and WordPress.com Simple sites.
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).
1089 1042 * They already get a menu item under Users via nav-unification.
1090 1043 */
1091 - if ( ( new Host() )->is_wpcom_platform() ) {
1044 + if ( ( new Host() )->is_wpcom_platform() && get_option( 'wpcom_admin_interface' ) !== 'wp-admin' ) {
1092 1045 return;
1093 1046 }
1094 1047
1095 1048 $status = new Status();
@@ -1104,22 +1057,66 @@
1104 1057 ) {
1105 1058 return;
1106 1059 }
1107 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 +
1108 1075 $link = Redirect::get_url(
1109 - 'jetpack-menu-calypso-subscribers',
1110 - array( 'site' => $status->get_site_suffix() )
1076 + 'jetpack-menu-jetpack-manage-subscribers',
1077 + array( 'site' => $blog_id ? $blog_id : $status->get_site_suffix() )
1111 1078 );
1112 1079
1113 - add_submenu_page(
1114 - 'jetpack',
1115 - esc_attr__( 'Subscribers', 'jetpack' ),
1116 - __( 'Subscribers', 'jetpack' ) . ' <span class="dashicons dashicons-external"></span>',
1080 + Admin_Menu::add_menu(
1081 + __( 'Subscribers', 'jetpack' ),
1082 + __( 'Subscribers', 'jetpack' ) . ' <span aria-hidden="true">↗</span>',
1117 1083 'manage_options',
1118 1084 esc_url( $link ),
1119 - null
1085 + null,
1086 + 100
1120 1087 );
1121 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 + }
1122 1119 }
1123 1120
1124 1121 Jetpack_Subscriptions::init();
1125 1122
@@ -1124,4 +1121,10 @@
1124 1121 Jetpack_Subscriptions::init();
1125 1122
1126 1123 require __DIR__ . '/subscriptions/views.php';
1127 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();