| @@ -68,8 +68,9 @@ | ||
| 68 | 68 | add_action( 'wp_ajax_' . self::SLUG_UNSUBSCRIBE, array( $this, 'unsubscribe_and_send_email' ) ); |
| 69 | 69 | add_action( 'wp_ajax_nopriv_' . self::SLUG_UNSUBSCRIBE, array( $this, 'unsubscribe_and_send_email' ) ); |
| 70 | 70 | add_action( 'defender_notify', array( $this, 'send_notify' ), 10, 2 ); |
| 71 | 71 | add_action( 'admin_notices', array( $this, 'show_actions_with_subscription' ) ); |
| 72 | + add_action( 'wp_footer', array( $this, 'show_public_subscription_notice' ) ); | |
| 72 | 73 | } |
| 73 | 74 | |
| 74 | 75 | /** |
| 75 | 76 | * For users who have subscribed or unsubscribed confirmation. |
| @@ -90,24 +91,12 @@ | ||
| 90 | 91 | } |
| 91 | 92 | $context = defender_get_data_from_request( 'context', 'g' ); |
| 92 | 93 | if ( 'subscribed' === $context ) { |
| 93 | 94 | $unsubscribe_link = $this->service->create_unsubscribe_url( $m->slug, $this->get_current_user_email() ); |
| 94 | - $strings = sprintf( | |
| 95 | - /* translators: 1. Module title. 2. Unsubscribed link. */ | |
| 96 | - esc_html__( | |
| 97 | - 'You are now subscribed to receive %1$s. Made a mistake? %2$s', | |
| 98 | - 'defender-security' | |
| 99 | - ), | |
| 100 | - '<strong>' . $m->title . '</strong>', | |
| 101 | - '<a href="' . esc_url_raw( $unsubscribe_link ) . '" style="text-decoration: none">' . esc_html__( 'Unsubscribe', 'defender-security' ) . '</a>' | |
| 102 | - ); | |
| 103 | - } elseif ( 'unsubscribe' === $context ) { | |
| 104 | - $strings = sprintf( | |
| 105 | - /* translators: %s: Module title. */ | |
| 106 | - esc_html__( 'You are now unsubscribed from %s.', 'defender-security' ), | |
| 107 | - '<strong>' . $m->title . '</strong>' | |
| 108 | - ); | |
| 109 | - } else { | |
| 95 | + } | |
| 96 | + | |
| 97 | + $strings = $this->get_subscription_notice_message( $m, $context, $unsubscribe_link ?? '' ); | |
| 98 | + if ( '' === $strings ) { | |
| 110 | 99 | return; |
| 111 | 100 | } |
| 112 | 101 | ?> |
| 113 | 102 | <div class="notice notice-success" style="position:relative;"> |
| @@ -120,8 +109,96 @@ | ||
| 120 | 109 | <?php |
| 121 | 110 | } |
| 122 | 111 | |
| 123 | 112 | /** |
| 113 | + * Show public confirmation notice for out-of-house recipients. | |
| 114 | + * | |
| 115 | + * @return void | |
| 116 | + */ | |
| 117 | + public function show_public_subscription_notice(): void { | |
| 118 | + $context = defender_get_data_from_request( 'defender_subscription', 'g' ); | |
| 119 | + if ( 'confirmed' !== $context && 'unsubscribe' !== $context ) { | |
| 120 | + return; | |
| 121 | + } | |
| 122 | + | |
| 123 | + $slug = defender_get_data_from_request( 'slug', 'g' ); | |
| 124 | + $hash = defender_get_data_from_request( 'hash', 'g' ); | |
| 125 | + if ( ! is_string( $slug ) || '' === trim( $slug ) ) { | |
| 126 | + return; | |
| 127 | + } | |
| 128 | + if ( 'confirmed' === $context && ( ! is_string( $hash ) || '' === trim( $hash ) ) ) { | |
| 129 | + return; | |
| 130 | + } | |
| 131 | + | |
| 132 | + $m = $this->service->find_module_by_slug( sanitize_key( $slug ) ); | |
| 133 | + if ( ! is_object( $m ) ) { | |
| 134 | + return; | |
| 135 | + } | |
| 136 | + | |
| 137 | + $unsubscribe_link = ''; | |
| 138 | + if ( 'confirmed' === $context ) { | |
| 139 | + $unsubscribe_link = add_query_arg( | |
| 140 | + array( | |
| 141 | + 'action' => self::SLUG_UNSUBSCRIBE, | |
| 142 | + 'hash' => sanitize_text_field( $hash ), | |
| 143 | + 'slug' => $m->slug, | |
| 144 | + ), | |
| 145 | + admin_url( 'admin-ajax.php' ) | |
| 146 | + ); | |
| 147 | + } | |
| 148 | + | |
| 149 | + $message = $this->get_subscription_notice_message( | |
| 150 | + $m, | |
| 151 | + 'confirmed' === $context ? 'subscribed' : 'unsubscribe', | |
| 152 | + $unsubscribe_link | |
| 153 | + ); | |
| 154 | + if ( '' === $message ) { | |
| 155 | + return; | |
| 156 | + } | |
| 157 | + ?> | |
| 158 | + <div class="wpdef-public-subscription-notice" style="position:fixed;right:20px;bottom:20px;z-index:99999;max-width:420px;padding:14px 18px;border-left:4px solid #00a32a;background:#fff;box-shadow:0 2px 12px rgba(0,0,0,.18);font:14px/1.5 -apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;color:#1d2327;"> | |
| 159 | + <?php echo wp_kses_post( $message ); ?> | |
| 160 | + </div> | |
| 161 | + <?php | |
| 162 | + } | |
| 163 | + | |
| 164 | + /** | |
| 165 | + * Build subscription notice message. | |
| 166 | + * | |
| 167 | + * @param object $module Notification module. | |
| 168 | + * @param string $context Notice context. | |
| 169 | + * @param string $unsubscribe_link Unsubscribe URL. | |
| 170 | + * @return string | |
| 171 | + */ | |
| 172 | + private function get_subscription_notice_message( object $module, string $context, string $unsubscribe_link = '' ): string { | |
| 173 | + if ( 'subscribed' === $context ) { | |
| 174 | + if ( '' === trim( $unsubscribe_link ) ) { | |
| 175 | + return ''; | |
| 176 | + } | |
| 177 | + | |
| 178 | + return sprintf( | |
| 179 | + /* translators: 1. Module title. 2. Unsubscribe link. */ | |
| 180 | + esc_html__( | |
| 181 | + 'You are now subscribed to receive %1$s. Made a mistake? %2$s', | |
| 182 | + 'defender-security' | |
| 183 | + ), | |
| 184 | + '<strong>' . esc_html( $module->title ) . '</strong>', | |
| 185 | + '<a href="' . esc_url( $unsubscribe_link ) . '" style="text-decoration: none">' . esc_html__( 'Unsubscribe', 'defender-security' ) . '</a>' | |
| 186 | + ); | |
| 187 | + } | |
| 188 | + | |
| 189 | + if ( 'unsubscribe' === $context ) { | |
| 190 | + return sprintf( | |
| 191 | + /* translators: %s: Module title. */ | |
| 192 | + esc_html__( 'You are now unsubscribed from %s.', 'defender-security' ), | |
| 193 | + '<strong>' . esc_html( $module->title ) . '</strong>' | |
| 194 | + ); | |
| 195 | + } | |
| 196 | + | |
| 197 | + return ''; | |
| 198 | + } | |
| 199 | + | |
| 200 | + /** | |
| 124 | 201 | * Renders the main view for this page. |
| 125 | 202 | */ |
| 126 | 203 | public function main_view() { |
| 127 | 204 | $this->render( 'main' ); |
| @@ -250,9 +327,10 @@ | ||
| 250 | 327 | $m = $this->service->find_module_by_slug( $slug ); |
| 251 | 328 | if ( ! is_object( $m ) ) { |
| 252 | 329 | wp_die( esc_html__( 'You shall not pass.', 'defender-security' ) ); |
| 253 | 330 | } |
| 254 | - $inhouse = false; | |
| 331 | + $inhouse = false; | |
| 332 | + $processed = false; | |
| 255 | 333 | foreach ( $m->in_house_recipients as &$recipient ) { |
| 256 | 334 | $email = $recipient['email']; |
| 257 | 335 | if ( hash_equals( $hash, hash( 'sha256', $email . AUTH_SALT ) ) ) { |
| 258 | 336 | // We skip even an un-logged user, because the admin can change the user's access without notice. |
| @@ -263,8 +341,9 @@ | ||
| 263 | 341 | $inhouse = true; |
| 264 | 342 | } |
| 265 | 343 | $recipient['status'] = Model_Notification::USER_SUBSCRIBE_CANCELED; |
| 266 | 344 | $m->save(); |
| 345 | + $processed = true; | |
| 267 | 346 | // Send email. |
| 268 | 347 | $this->service->send_unsubscribe_email( $m, $email, $inhouse, $recipient['name'] ); |
| 269 | 348 | break; |
| 270 | 349 | } |
| @@ -276,8 +355,9 @@ | ||
| 276 | 355 | $email = $recipient['email']; |
| 277 | 356 | if ( hash_equals( $hash, hash( 'sha256', $email . AUTH_SALT ) ) ) { |
| 278 | 357 | $recipient['status'] = Model_Notification::USER_SUBSCRIBE_CANCELED; |
| 279 | 358 | $m->save(); |
| 359 | + $processed = true; | |
| 280 | 360 | $this->service->send_unsubscribe_email( $m, $email, $inhouse, $recipient['name'] ); |
| 281 | 361 | } |
| 282 | 362 | } |
| 283 | 363 | } |
| @@ -290,8 +370,18 @@ | ||
| 290 | 370 | ), |
| 291 | 371 | get_edit_profile_url() |
| 292 | 372 | ) |
| 293 | 373 | ); |
| 374 | + } elseif ( $processed ) { | |
| 375 | + wp_safe_redirect( | |
| 376 | + add_query_arg( | |
| 377 | + array( | |
| 378 | + 'defender_subscription' => 'unsubscribe', | |
| 379 | + 'slug' => $slug, | |
| 380 | + ), | |
| 381 | + get_home_url() | |
| 382 | + ) | |
| 383 | + ); | |
| 294 | 384 | } else { |
| 295 | 385 | wp_safe_redirect( get_home_url() ); |
| 296 | 386 | } |
| 297 | 387 | exit; |
| @@ -657,9 +747,8 @@ | ||
| 657 | 747 | public function enqueue_assets() { |
| 658 | 748 | if ( ! $this->is_page_active() ) { |
| 659 | 749 | return; |
| 660 | 750 | } |
| 661 | - // todo: add changes when the design is ready. | |
| 662 | 751 | } |
| 663 | 752 | |
| 664 | 753 | /** |
| 665 | 754 | * An endpoint for fetching users pool. |
| @@ -783,9 +872,8 @@ | ||
| 783 | 872 | return array(); |
| 784 | 873 | } |
| 785 | 874 | |
| 786 | 875 | /** |
| 787 | - * Todo: add changes when the design is ready. | |
| 788 | 876 | * Provides data for the frontend. |
| 789 | 877 | * |
| 790 | 878 | * @return array An array of data for the frontend. |
| 791 | 879 | */ |