Changeset 11580 for sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-bbp-term-subscription/inc/class-plugin.php
- Timestamp:
- 02/18/2022 03:02:37 AM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sites/trunk/wordpress.org/public_html/wp-content/plugins/wporg-bbp-term-subscription/inc/class-plugin.php
r11533 r11580 7 7 /** 8 8 * @todo AJAXify subscription action. 9 * @todo Add unsubscribe link to outgoing emails. 10 */ 11 12 private $subscribers = array(); 9 */ 13 10 14 11 public $taxonomy = false; … … 16 13 public $directory = false; 17 14 15 protected $term = false; 16 protected $subscribers = array(); 17 18 18 const META_KEY = '_bbp_term_subscription'; 19 20 /** 21 * Valid actions for this plugin. 22 */ 23 const VALID_ACTIONS = array( 24 'wporg_bbp_subscribe_term', 25 'wporg_bbp_unsubscribe_term', 26 ); 27 28 /** 29 * Length of time the unsubscription links are valid. 30 * 31 * @var int 32 */ 33 const UNSUBSCRIBE_LIFETIME = 604800; // WEEK_IN_SECONDS 19 34 20 35 public function __construct( $args = array() ) { … … 26 41 'subscribed_user_notice' => __( 'You are not currently subscribed to any topic tags.', 'wporg-forums' ), 27 42 'subscribed_anon_notice' => __( 'This user is not currently subscribed to any topic tags.', 'wporg-forums' ), 28 'receipt' => __( 'You are receiving this email because you are subscribed to a topic tag.', 'wporg-forums'),43 'receipt' => __( "You are receiving this email because you are subscribed to the %s tag.", 'wporg-forums'), 29 44 ), 30 45 ) ); … … 34 49 $this->directory = $r['directory']; 35 50 36 add_action( 'bbp_init', array( $this, 'bbp_init' ) ); 37 } 38 39 /** 40 * Initialize the plugin. 41 */ 42 public function bbp_init() { 43 // If the user isn't logged in, there will be no topics or replies added. 44 if ( ! is_user_logged_in() ) { 45 return; 46 } 47 51 // If no taxonomy was provided, there's nothing we can do. 48 52 if ( ! $this->taxonomy ) { 49 53 return; 50 54 } 51 55 56 add_action( 'bbp_init', array( $this, 'bbp_init' ) ); 57 } 58 59 /** 60 * Initialize the plugin. 61 */ 62 public function bbp_init() { 52 63 // Add views and actions for users. 53 64 add_action( 'bbp_get_request', array( $this, 'term_subscribe_handler' ) ); 65 add_action( 'bbp_post_request', array( $this, 'term_subscribe_handler' ) ); 66 add_action( 'bbp_template_redirect', array( $this, 'fix_bbpress_post_actions' ), 9 ); // before bbp_get_request/bbp_post_request 54 67 55 68 // Notify subscribers when a topic or reply with a given term is added. … … 62 75 add_filter( 'bbp_subscription_mail_title', array( $this, 'replace_topic_subscription_mail_title' ), 10, 3 ); 63 76 77 // Add a section to the user subscriptions list to allow management of subscriptions. 64 78 add_action( 'bbp_template_after_user_subscriptions', array( $this, 'user_subscriptions' ) ); 65 79 … … 70 84 71 85 /** 86 * bbPress has two action handlers, GET and POST, a POST action cannot work with ?action= from the URL. 87 * 88 * This is used by the email-unsubscription handler. 89 */ 90 public function fix_bbpress_post_actions() { 91 if ( 92 bbp_is_post_request() && 93 empty( $_POST['action'] ) && 94 ! empty( $_GET['action'] ) && 95 in_array( $_GET['action'], self::VALID_ACTIONS, true ) 96 ) { 97 $_POST['action'] = $_GET['action']; 98 } 99 } 100 101 /** 72 102 * Add a notice that you're subscribed to the tag/plugin/theme, or have just unsubscribed. 73 103 */ 74 104 public function before_view() { 75 $term = false; 76 77 if ( $this->directory && $this->directory->slug && $this->directory->term ) { 78 $term = $this->directory->term; 79 $term_name = $this->directory->title(); 80 } elseif ( bbp_is_topic_tag() ) { 81 $term = get_queried_object(); 82 if ( empty( $term->taxonomy ) || $term->taxonomy !== $this->taxonomy ) { 83 return; 84 } 85 86 $term_name = $term->name; 87 } 88 89 if ( empty( $term->term_id ) ) { 105 $term = $this->get_current_term(); 106 107 if ( ! $term || $term->taxonomy !== $this->taxonomy ) { 90 108 return; 91 109 } 110 111 do_action( 'bbp_template_notices' ); 92 112 93 113 $is_subscribed = self::is_user_subscribed_to_term( get_current_user_id(), $term->term_id ); … … 95 115 if ( $is_subscribed ) { 96 116 $message = sprintf( 97 __( 'You are subscribed to this forum, and will receive emails for future topic activity. <a href="%1$s">Unsubscribe from %2$s </a>', 'wporg-forums' ),117 __( 'You are subscribed to this forum, and will receive emails for future topic activity. <a href="%1$s">Unsubscribe from %2$s.</a>', 'wporg-forums' ), 98 118 self::get_subscription_url( get_current_user_id(), $term->term_id, $this->taxonomy ), 99 esc_html( $term _name )119 esc_html( $term->name ) 100 120 ); 101 121 } elseif ( ! empty( $_GET['success'] ) && 'subscription-removed' === $_GET['success'] ) { 102 122 $message = sprintf( 103 123 __( 'You have been unsubscribed from future emails for %1$s.', 'wporg-forums' ), 104 esc_html( $term _name )124 esc_html( $term->name ) 105 125 ); 106 126 } else { … … 122 142 public function term_subscribe_handler( $action = '' ) { 123 143 // Bail if the actions aren't meant for this function. 124 if ( ! in_array( $action, self:: get_valid_actions()) ) {144 if ( ! in_array( $action, self::VALID_ACTIONS ) ) { 125 145 return; 126 146 } 127 147 128 if ( ! $this->taxonomy ) { 148 if ( ! bbp_is_subscriptions_active() ) { 149 return false; 150 } 151 152 // Determine the term the request is for, overwrite with ?term_id if specified. 153 $term = $this->get_current_term(); 154 if ( ! empty( $_GET['term_id'] ) ) { 155 $term = get_term( intval( $_GET['term_id'] ), $this->taxonomy ); 156 } 157 if ( ! $term ) { 129 158 return; 130 159 } 131 160 132 // Taxonomy mismatch; a different instance should handle this. 133 if ( ! isset( $_GET['taxonomy'] ) || $this->taxonomy != $_GET['taxonomy'] ) { 134 return; 135 } 136 137 if ( ! bbp_is_subscriptions_active() ) { 138 return false; 139 } 140 141 // Bail if the actions aren't meant for this function. 142 if ( ! in_array( $action, self::get_valid_actions() ) ) { 143 return; 144 } 145 146 // Bail if no term id is passed. 147 if ( ! isset( $_GET['term_id'] ) || empty( $_GET['term_id'] ) ) { 148 return; 149 } 150 151 // Get required data. 161 $term_id = $term->term_id; 162 $auth = 'nonce'; 152 163 $user_id = get_current_user_id(); 153 $term_id = intval( $_GET['term_id'] ); 154 $term = get_term( $term_id, $this->taxonomy ); 164 165 // If a user_id + token is provided, verify the request and maybe use the provided user_id. 166 if ( isset( $_GET['token'] ) ) { 167 $auth = 'token'; 168 $user_id = $this->has_valid_unsubscription_token(); 169 170 if ( ! $user_id ) { 171 bbp_add_error( 'wporg_bbp_subscribe_invalid_token', __( '<strong>ERROR</strong>: Link expired!', 'wporg-forums' ) ); 172 return false; 173 } 174 175 // Require a POST request for verification. Gmail will bypass this for one-click unsubscriptions by POST'ing to the URL. 176 if ( empty( $_POST ) ) { 177 wp_die( 178 sprintf( 179 '<h1>%1$s</h1>' . 180 '<p>%2$s</p>' . 181 '<form method="POST" action="%3$s">' . 182 '<input type="submit" name="confirm" value="%4$s">' . 183 ' <a href="%5$s">%6$s</a>' . 184 '</form>', 185 get_bloginfo('name'), 186 sprintf( 187 /* translators: 1: Plugin, Theme, or Tag name. */ 188 esc_html__( 'Do you wish to unsubscribe from future emails for %s?', 'wporg-forums' ), 189 $term->name 190 ), 191 esc_attr( $_SERVER['REQUEST_URI'] ), 192 esc_attr__( 'Yes, unsubscribe me', 'wporg-forums' ), 193 get_term_link( $term ), 194 sprintf( 195 /* translators: 1: Plugin, Theme, or Tag name. */ 196 esc_attr__( 'No, take me to the %s forum.', 'wporg-forums' ), 197 $term->name 198 ) 199 ) 200 ); 201 exit; 202 } 203 204 } 155 205 156 206 // Check for empty term id. 157 if ( ! $term ) { 158 /* translators: Term: topic tag */ 159 bbp_add_error( 'wporg_bbp_subscribe_term_id', __( '<strong>ERROR</strong>: No term was found! Which term are you subscribing/unsubscribing to?', 'wporg-forums' ) ); 160 161 // Check for current user. 162 } elseif ( empty( $user_id ) ) { 207 if ( empty( $user_id ) ) { 163 208 bbp_add_error( 'wporg_bbp_subscribe_logged_id', __( '<strong>ERROR</strong>: You must be logged in to do this!', 'wporg-forums' ) ); 164 209 165 210 // Check nonce. 166 } elseif ( ! bbp_verify_nonce_request( 'toggle-term-subscription_' . $user_id . '_' . $term_id . '_' . $this->taxonomy ) ) {211 } elseif ( 'nonce' === $auth && ! bbp_verify_nonce_request( 'toggle-term-subscription_' . $user_id . '_' . $term_id . '_' . $this->taxonomy ) ) { 167 212 bbp_add_error( 'wporg_bbp_subscribe_nonce', __( '<strong>ERROR</strong>: Are you sure you wanted to do that?', 'wporg-forums' ) ); 168 213 169 // Check currentuser's ability to spectate.170 } elseif ( ! current_user_can('spectate' ) ) {214 // Check user's ability to spectate. 215 } elseif ( ! user_can( $user_id, 'spectate' ) ) { 171 216 bbp_add_error( 'wporg_bbp_subscribe_permissions', __( '<strong>ERROR</strong>: You don\'t have permission to do this!', 'wporg-forums' ) ); 172 217 } … … 176 221 } 177 222 223 $success = false; 178 224 $is_subscribed = self::is_user_subscribed_to_term( $user_id, $term_id ); 179 $success = false; 180 181 if ( true === $is_subscribed && 'wporg_bbp_unsubscribe_term' === $action ) { 182 $success = self::remove_user_subscription( $user_id, $term_id ); 183 } elseif ( false === $is_subscribed && 'wporg_bbp_subscribe_term' === $action ) { 184 $success = self::add_user_subscription( $user_id, $term_id ); 225 226 if ( 'wporg_bbp_unsubscribe_term' === $action ) { 227 $success = ! $is_subscribed || self::remove_user_subscription( $user_id, $term_id ); 228 } elseif ( 'wporg_bbp_subscribe_term' === $action ) { 229 $success = $is_subscribed || self::add_user_subscription( $user_id, $term_id ); 185 230 } 186 231 … … 224 269 } 225 270 226 foreach ( $terms as $term ) { 227 $subscribers = $this->get_term_subscribers( $term->term_id ); 228 if ( $subscribers ) { 229 $this->subscribers = array_unique( array_merge( $subscribers, $this->subscribers ) ); 230 } 231 } 271 // Users that will be notified another way, or have already been notified. 272 $notified_users = array(); 273 274 // Remove the author from being notified of their own topic. 275 $notified_users[] = bbp_get_topic_author_id( $topic_id ); 232 276 233 277 // Get users who were already notified and exclude them. 234 278 $forum_subscribers = bbp_get_forum_subscribers( $forum_id, true ); 235 279 if ( ! empty( $forum_subscribers ) ) { 236 $this->subscribers = array_diff( $this->subscribers, $forum_subscribers ); 237 } 238 239 // Remove the author from being notified of their own topic. 240 $this->subscribers = array_diff( $this->subscribers, array( bbp_get_topic_author_id( $topic_id ) ) ); 241 242 if ( empty( $this->subscribers ) ) { 243 return; 280 $notified_users = array_merge( $notified_users, $forum_subscribers ); 244 281 } 245 282 … … 250 287 add_filter( 'bbp_forum_subscription_user_ids', array( $this, 'add_term_subscribers' ) ); 251 288 252 // Actually notify our term subscribers. 253 bbp_notify_forum_subscribers( $topic_id, $forum_id ); 289 // Personalize the emails. 290 add_filter( 'wporg_bbp_subscription_email', array( $this, 'personalize_subscription_email' ) ); 291 292 foreach ( $terms as $term ) { 293 $subscribers = $this->get_term_subscribers( $term->term_id ); 294 if ( ! $subscribers ) { 295 continue; 296 } 297 298 $subscribers = array_diff( $subscribers, $notified_users ); 299 if ( ! $subscribers ) { 300 continue; 301 } 302 303 $this->term = $term; 304 $this->subscribers = $subscribers; 305 306 // Actually notify the term subscribers. 307 bbp_notify_forum_subscribers( $topic_id, $forum_id ); 308 309 // Don't email them twice. 310 $notified_users = array_merge( $notified_users, $subscribers ); 311 } 312 313 // Reset 314 $this->term = false; 315 $this->subscribers = array(); 254 316 255 317 // Remove filters. 318 remove_filter( 'bbp_forum_subscription_mail_message', array( $this, 'replace_forum_subscription_mail_message' ) ); 256 319 remove_filter( 'bbp_forum_subscription_user_ids', array( $this, 'add_term_subscribers' ) ); 257 remove_filter( 'bbp_forum_subscription_mail_message', array( $this, 'replace_forum_subscription_mail_message' ), 10 ); 258 320 remove_filter( 'wporg_bbp_subscription_email', array( $this, 'personalize_subscription_email' ) ); 259 321 } 260 322 … … 284 346 $topic_url = get_permalink( $topic_id ); 285 347 286 $message = sprintf( __( '%1$s wrote: 348 $message = sprintf( 349 /* translators: 1: Author, 2: Forum message, 3: Link to topic, 4: Descriptive text of why they're getting the email */ 350 __( '%1$s wrote: 287 351 288 352 %2$s 289 353 290 TopicLink: %3$s354 Link: %3$s 291 355 292 356 ----------- 293 357 358 To reply, visit the above link and log in. 359 Note that replying to this email has no effect. 360 294 361 %4$s 295 362 296 Log in and visit the topic to reply to the topic or unsubscribe from these emails. Note that replying to this email has no effect.', 'wporg-forums' ), 363 To unsubscribe from future emails click here: 364 ####UNSUB_LINK####', 'wporg-forums' ), 297 365 $topic_author_name, 298 366 $topic_content, 299 367 $topic_url, 300 // String may not have placeholders, ie. in the case of tags. 301 sprintf( $this->labels['receipt'], $this->directory ? $this->directory->title() : '' ) 368 sprintf( 369 $this->labels['receipt'], 370 $this->get_current_term()->name 371 ) 302 372 ); 303 373 … … 345 415 } 346 416 347 foreach ( $terms as $term ) { 348 $subscribers = $this->get_term_subscribers( $term->term_id ); 349 if ( $subscribers ) { 350 $this->subscribers = array_unique( array_merge( $subscribers, $this->subscribers ) ); 351 } 352 } 417 // Users that will be notified another way, or have already been notified. 418 $notified_users = array(); 419 420 // Remove the author from being notified of their own topic. 421 $notified_users[] = bbp_get_reply_author_id( $reply_id ); 353 422 354 423 // Get users who were already notified and exclude them. 355 424 $topic_subscribers = bbp_get_topic_subscribers( $topic_id, true ); 356 425 if ( ! empty( $topic_subscribers ) ) { 357 $this->subscribers = array_diff( $this->subscribers, $topic_subscribers ); 358 } 359 360 // Remove the author from being notified of their own reply. 361 $this->subscribers = array_diff( $this->subscribers, array( bbp_get_reply_author_id( $reply_id ) ) ); 362 363 if ( empty( $this->subscribers ) ) { 364 return; 426 $notified_users = array_merge( $notified_users, $topic_subscribers ); 365 427 } 366 428 … … 371 433 add_filter( 'bbp_topic_subscription_user_ids', array( $this, 'add_term_subscribers' ) ); 372 434 373 // Actually notify our term subscribers. 374 bbp_notify_topic_subscribers( $reply_id, $topic_id, $forum_id ); 435 // Personalize the emails. 436 add_filter( 'wporg_bbp_subscription_email', array( $this, 'personalize_subscription_email' ) ); 437 438 foreach ( $terms as $term ) { 439 $subscribers = $this->get_term_subscribers( $term->term_id ); 440 if ( ! $subscribers ) { 441 continue; 442 } 443 444 $subscribers = array_diff( $subscribers, $notified_users ); 445 if ( ! $subscribers ) { 446 continue; 447 } 448 449 $this->term = $term; 450 $this->subscribers = $subscribers; 451 452 // Actually notify our term subscribers. 453 bbp_notify_topic_subscribers( $reply_id, $topic_id, $forum_id ); 454 455 // Don't email them twice. 456 $notified_users = array_merge( $notified_users, $subscribers ); 457 } 458 459 // Reset 460 $this->term = false; 461 $this->subscribers = array(); 375 462 376 463 // Remove filters. 464 remove_filter( 'bbp_subscription_mail_message', array( $this, 'replace_topic_subscription_mail_message' ) ); 377 465 remove_filter( 'bbp_topic_subscription_user_ids', array( $this, 'add_term_subscribers' ) ); 378 remove_filter( ' bbp_subscription_mail_message', array( $this, 'replace_topic_subscription_mail_message' ) );466 remove_filter( 'wporg_bbp_subscription_email', array( $this, 'personalize_subscription_email' ) ); 379 467 } 380 468 … … 396 484 $reply_url = bbp_get_reply_url( $reply_id ); 397 485 398 $message = sprintf( __( '%1$s wrote: 486 $message = sprintf( 487 /* translators: 1: Author, 2: Forum message, 3: Link to topic, 4: Descriptive text of why they're getting the email */ 488 __( '%1$s wrote: 399 489 400 490 %2$s 401 491 402 ReplyLink: %3$s492 Link: %3$s 403 493 404 494 ----------- 405 495 496 To reply, visit the above link and log in. 497 Note that replying to this email has no effect. 498 406 499 %4$s 407 500 408 Log in and visit the topic to reply to the topic or unsubscribe from these emails. Note that replying to this email has no effect.', 'wporg-forums' ), 501 To unsubscribe from future emails click here: 502 ####UNSUB_LINK####', 'wporg-forums' ), 409 503 $reply_author_name, 410 504 $reply_content, 411 505 $reply_url, 412 // String may not have placeholders, ie. in the case of tags. 413 sprintf( $this->labels['receipt'], $this->directory ? $this->directory->title() : '' ) 506 sprintf( 507 $this->labels['receipt'], 508 $this->get_current_term()->name 509 ) 414 510 ); 415 511 … … 439 535 440 536 return $title; 537 } 538 539 /** 540 * Personalize subscription emails by adding an unsubscription link. 541 * 542 * @param array $email_parts The email parts. 543 * @return The email parts. 544 */ 545 public function personalize_subscription_email( $email_parts ) { 546 // get_tokenised_unsubscribe_url() will validate the user object. 547 $user = get_user_by( 'email', $email_parts['to'] ); 548 $unsub_link = $this->get_tokenised_unsubscribe_url( $user, $this->term ); 549 550 if ( ! $unsub_link ) { 551 return $email_parts; 552 } 553 554 $email_parts['message'] = str_replace( 555 '####UNSUB_LINK####', 556 '<' . esc_url_raw( $unsub_link ) . '>', 557 $email_parts['message'] 558 ); 559 560 $email_parts['headers'][] = 'List-Unsubscribe: <' . esc_url_raw( $unsub_link ) . '>'; 561 $email_parts['headers'][] = 'List-Unsubscribe-Post: List-Unsubscribe=One-Click'; 562 563 return $email_parts; 564 } 565 566 /** 567 * Get the WP_Term instance for the currently displayed item. 568 */ 569 protected function get_current_term() { 570 if ( $this->term ) { 571 return $this->term; 572 } 573 574 // The currently queried tag. 575 if ( 576 bbp_is_topic_tag() && 577 ( $term = get_queried_object() ) && 578 ( $term instanceof \WP_Term ) 579 ) { 580 return $term; 581 } 582 583 // The current directory loaded. 584 if ( 585 $this->directory && 586 bbp_is_single_view() && 587 $this->directory->compat() == bbp_get_view_id() 588 ) { 589 return $this->directory->term; 590 } 591 592 return false; 441 593 } 442 594 … … 465 617 echo '<p id="bbp-term-' . esc_attr( $this->taxonomy ) . '">' . "\n"; 466 618 foreach ( $terms as $term ) { 467 echo '<a href="' . esc_url( get_term_link( $term->term_id ) ) . '">' . esc_html( $term-> slug) . '</a>';619 echo '<a href="' . esc_url( get_term_link( $term->term_id ) ) . '">' . esc_html( $term->name ) . '</a>'; 468 620 if ( get_current_user_id() == $user_id ) { 469 621 $url = self::get_subscription_url( $user_id, $term->term_id, $this->taxonomy ); … … 495 647 */ 496 648 public static function get_user_taxonomy_subscriptions( $user_id = 0, $taxonomy = 'topic-tag' ) { 497 $retval = false;498 499 649 if ( empty( $user_id ) || empty( $taxonomy ) ) { 500 650 return false; 501 651 } 502 652 503 $ terms = get_terms( array(653 $subscriptions = get_terms( array( 504 654 'taxonomy' => $taxonomy, 505 655 'meta_key' => self::META_KEY, … … 507 657 ) ); 508 658 509 if ( ! empty( $terms ) ) {510 $retval = $terms;511 } 512 return apply_filters( 'wporg_bbp_get_user_taxonomy_subscriptions', $ retval, $user_id, $taxonomy );659 // Default to false if empty. 660 $subscriptions = $subscriptions ?: false; 661 662 return apply_filters( 'wporg_bbp_get_user_taxonomy_subscriptions', $subscriptions, $user_id, $taxonomy ); 513 663 } 514 664 … … 529 679 wp_cache_set( 'wporg_bbp_get_term_subscribers_' . $term_id, $subscribers, 'bbpress_users' ); 530 680 } 681 531 682 return apply_filters( 'wporg_bbp_get_term_subscribers', $subscribers, $term_id ); 532 683 } … … 619 770 620 771 if ( self::is_user_subscribed_to_term( $user_id, $term_id ) ) { 621 $ query_args = array( 'action' => 'wporg_bbp_unsubscribe_term', 'term_id' => $term_id, 'taxonomy' => $taxonomy );772 $action = 'wporg_bbp_unsubscribe_term'; 622 773 } else { 623 $ query_args = array( 'action' => 'wporg_bbp_subscribe_term', 'term_id' => $term_id, 'taxonomy' => $taxonomy );774 $action = 'wporg_bbp_subscribe_term'; 624 775 } 625 776 … … 630 781 } 631 782 632 $url = esc_url( wp_nonce_url( add_query_arg( $query_args, $permalink ), 'toggle-term-subscription_' . $user_id . '_' . $term_id . '_' . $taxonomy ) ); 633 return $url; 634 } 635 783 $url = wp_nonce_url( 784 add_query_arg( compact( 'action', 'term_id' ), $permalink ), 785 'toggle-term-subscription_' . $user_id . '_' . $term_id . '_' . $taxonomy 786 ); 787 788 return esc_url( $url ); 789 } 790 791 /** 792 * Generates a unsubscription token for a user. 793 * 794 * The token form is 'user_id|expiry|hash', and dependant upon the user email, password, and term. 795 * 796 * @param WP_Term $term The user the token should be for. 797 * @param WP_User $user The user the token should be for. 798 * @param int $expiry The expiry of the token. Optional, only required for verifying tokens. 799 * @return string|bool The hashed token, false on failure. 800 */ 801 protected static function generate_unsubscribe_token( $term, $user, $expiry = 0 ) { 802 if ( ! $term || ! $user ) { 803 return false; 804 } 805 if ( ! $expiry ) { 806 $expiry = time() + self::UNSUBSCRIBE_LIFETIME; 807 } 808 809 $expiry = intval( $expiry ); 810 $pass_frag = substr( $user->user_pass, 8, 4 ); // Password fragment used by cookie auth. 811 $key = wp_hash( $term->term_id . '|' . $term->taxonomy . '|' . $user->user_email . '|' . $pass_frag . '|' . $expiry, 'forum_subcriptions' ); 812 $hash = hash_hmac( 'sha256', $term->term_id . '|' . $term->taxonomy . '|' . $user->user_email . '|' . $expiry, $key ); 813 814 return $user->ID . '|' . $expiry . '|' . $hash; 815 } 816 817 /** 818 * Validate if the current request has a valid tokenised unsubscription link. 819 * 820 * @return bool|int User ID on success, false on failure. 821 */ 822 protected function has_valid_unsubscription_token() { 823 if ( 824 ! isset( $_GET['token'] ) || 825 2 !== substr_count( $_GET['token'], '|' ) 826 ) { 827 return false; 828 } 829 830 $provided_token = rtrim( $_GET['token'], '>' ); 831 list( $user_id, $expiry, ) = explode( '|', $provided_token ); 832 $term = $this->get_current_term(); 833 $user = get_user_by( 'id', intval( $user_id ) ); 834 $expected_token = self::generate_unsubscribe_token( $term, $user, $expiry ); 835 836 if ( 837 $expiry > time() && 838 hash_equals( $expected_token, $provided_token ) 839 ) { 840 return $user->ID; 841 } 842 843 return false; 844 } 845 846 /** 847 * Generate a tokenised unsubscription link for a given user & term. 848 * 849 * This link can be used without being logged in. 850 * 851 * @param \WP_User $user The user to generate the link for. 852 * @param \WP_Term $term The term to generate the link for. 853 * 854 * @return bool|string The URL, or false upon failure. 855 */ 856 public static function get_tokenised_unsubscribe_url( $user, $term ) { 857 $token = self::generate_unsubscribe_token( $term, $user ); 858 if ( ! $token ) { 859 return false; 860 } 861 862 return add_query_arg( 863 array( 864 'action' => 'wporg_bbp_unsubscribe_term', 865 'token' => $token, 866 ), 867 // We don't include the term_id in the URL, and instead rely upon the term coming from the URL 868 get_term_link( $term ) 869 ); 870 } 871 872 /** 873 * Generate an unsubscription link for use in a Template. 874 * 875 * @param array $args 876 * @return string 877 */ 636 878 public static function get_subscription_link( $args ) { 637 if ( ! current_user_can( 'spectate' ) ) {638 return false;639 }640 641 879 $r = bbp_parse_args( $args, array( 642 880 'user_id' => get_current_user_id(), … … 648 886 'js_confirm' => esc_html__( 'Are you sure you wish to subscribe by email to all future topics created in this tag?', 'wporg-forums' ), 649 887 ), 'get_term_subscription_link' ); 650 if ( empty( $r['user_id'] ) || empty( $r['term_id'] ) || empty( $r['taxonomy'] ) ) {651 return false;652 }653 888 654 889 $user_id = $r['user_id']; … … 656 891 $taxonomy = $r['taxonomy']; 657 892 658 $url = self::get_subscription_url( $r['user_id'], $r['term_id'], $r['taxonomy'] ); 659 if ( self::is_user_subscribed_to_term( $r['user_id'], $r['term_id'] ) ) { 893 if ( empty( $user_id ) || empty( $term_id ) || empty( $taxonomy ) ) { 894 return false; 895 } 896 897 if ( ! user_can( $user_id, 'spectate' ) ) { 898 return false; 899 } 900 901 $url = self::get_subscription_url( $user_id, $term_id, $taxonomy ); 902 if ( self::is_user_subscribed_to_term( $user_id, $term_id ) ) { 660 903 $text = $r['unsubscribe']; 661 904 $js_confirm = ''; … … 673 916 ); 674 917 } 675 676 public static function get_valid_actions() {677 return array(678 'wporg_bbp_subscribe_term',679 'wporg_bbp_unsubscribe_term',680 );681 }682 918 }
Note: See TracChangeset
for help on using the changeset viewer.