| 512 | |
| 513 | if ( ! class_exists( 'BBP_Topic' ) ) : |
| 514 | /** |
| 515 | * bbPress Topic Class |
| 516 | * |
| 517 | * The bbPress component class is responsible for simplifying the creation |
| 518 | * of topics |
| 519 | * |
| 520 | * @package bbPress |
| 521 | * @subpackage Classes |
| 522 | * |
| 523 | * @since 2.7 |
| 524 | */ |
| 525 | class BBP_Topic { |
| 526 | /** |
| 527 | * The id of newly created topic |
| 528 | * @var int |
| 529 | */ |
| 530 | public $id; |
| 531 | |
| 532 | /** |
| 533 | * Topic data |
| 534 | * @var array|mixed |
| 535 | */ |
| 536 | private $data = []; |
| 537 | |
| 538 | /** |
| 539 | * Whether we want to bbp_redirect after saving |
| 540 | * @var bool |
| 541 | */ |
| 542 | private $should_redirect_after = true; |
| 543 | |
| 544 | /** Methods ***************************************************************/ |
| 545 | |
| 546 | /** |
| 547 | * bbPress create new Topic class |
| 548 | * |
| 549 | * @since 2.7 bbPress () |
| 550 | * |
| 551 | * @param array $data Optional, topic data (for bbPress frontend it should be $_POST) |
| 552 | * @param boolean $should_redirect_after Optional. Whether we want to redirect after saving |
| 553 | */ |
| 554 | public function __construct( $data = [], $should_redirect_after = true ) { |
| 555 | $this->data = $data; |
| 556 | $this->should_redirect_after = $should_redirect_after; |
| 557 | } |
| 558 | |
| 559 | /** |
| 560 | * Get anonymous data if user is not logged in |
| 561 | * @return array|bool |
| 562 | */ |
| 563 | private function get_anonymous_data() { |
| 564 | // Filter anonymous data (variable is used later) |
| 565 | $anonymous_data = bbp_filter_anonymous_post_data( $this->data ); |
| 566 | |
| 567 | // Anonymous data checks out, so set cookies, etc... |
| 568 | bbp_set_current_anonymous_user_data( $anonymous_data ); |
| 569 | |
| 570 | return $anonymous_data; |
| 571 | } |
| 572 | |
| 573 | /** |
| 574 | * Get topic author id |
| 575 | * @return int |
| 576 | */ |
| 577 | private function get_topic_author_id() { |
| 578 | // User cannot create topics |
| 579 | if ( ! current_user_can( 'publish_topics' ) ) { |
| 580 | bbp_add_error( 'bbp_topic_permission', __( '<strong>Error</strong>: You do not have permission to create new topics.', 'bbpress' ) ); |
| 581 | return 0; |
| 582 | } |
| 583 | |
| 584 | // Topic author is current user |
| 585 | return bbp_get_current_user_id(); |
| 586 | } |
| 587 | |
| 588 | /** |
| 589 | * Get topic validated and sanitized title |
| 590 | * @return string |
| 591 | */ |
| 592 | private function get_topic_title() { |
| 593 | $topic_title = ''; |
| 594 | if ( ! empty( $this->data['bbp_topic_title'] ) ) { |
| 595 | $topic_title = sanitize_text_field( $this->data['bbp_topic_title'] ); |
| 596 | } |
| 597 | |
| 598 | // Filter and sanitize |
| 599 | $topic_title = apply_filters( 'bbp_new_topic_pre_title', $topic_title ); |
| 600 | |
| 601 | // No topic title |
| 602 | if ( empty( $topic_title ) ) { |
| 603 | bbp_add_error( 'bbp_topic_title', __( '<strong>Error</strong>: Your topic needs a title.', 'bbpress' ) ); |
| 604 | return ''; |
| 605 | } |
| 606 | |
| 607 | // Title too long |
| 608 | if ( bbp_is_title_too_long( $topic_title ) ) { |
| 609 | bbp_add_error( 'bbp_topic_title', __( '<strong>Error</strong>: Your title is too long.', 'bbpress' ) ); |
| 610 | return ''; |
| 611 | } |
| 612 | |
| 613 | return $topic_title; |
| 614 | } |
| 615 | |
| 616 | /** |
| 617 | * Get topic validated and sanitized content |
| 618 | * @return string |
| 619 | */ |
| 620 | private function get_topic_content() { |
| 621 | $topic_content = ''; |
| 622 | if ( ! empty( $this->data['bbp_topic_content'] ) ) { |
| 623 | $topic_content = $this->data['bbp_topic_content']; |
| 624 | } |
| 625 | |
| 626 | // Filter and sanitize |
| 627 | $topic_content = apply_filters( 'bbp_new_topic_pre_content', $topic_content ); |
| 628 | |
| 629 | // No topic content |
| 630 | if ( empty( $topic_content ) ) { |
| 631 | bbp_add_error( 'bbp_topic_content', __( '<strong>Error</strong>: Your topic cannot be empty.', 'bbpress' ) ); |
| 632 | return ''; |
| 633 | } |
| 634 | |
| 635 | return $topic_content; |
| 636 | } |
| 637 | |
| 638 | /** |
| 639 | * Get validated forum id |
| 640 | * @return int |
| 641 | */ |
| 642 | private function get_forum_id() { |
| 643 | $forum_id = 0; |
| 644 | // Error check the POST'ed topic id |
| 645 | if ( isset( $this->data['bbp_forum_id'] ) ) { |
| 646 | |
| 647 | // Empty Forum id was passed |
| 648 | if ( empty( $this->data['bbp_forum_id'] ) ) { |
| 649 | bbp_add_error( 'bbp_topic_forum_id', __( '<strong>Error</strong>: Forum ID is missing.', 'bbpress' ) ); |
| 650 | return 0; |
| 651 | |
| 652 | // Forum id is not a number |
| 653 | } elseif ( ! is_numeric( $this->data['bbp_forum_id'] ) ) { |
| 654 | bbp_add_error( 'bbp_topic_forum_id', __( '<strong>Error</strong>: Forum ID must be a number.', 'bbpress' ) ); |
| 655 | return 0; |
| 656 | |
| 657 | // Forum id might be valid |
| 658 | } else { |
| 659 | |
| 660 | // Get the forum id |
| 661 | $posted_forum_id = intval( $this->data['bbp_forum_id'] ); |
| 662 | |
| 663 | // Forum id is empty |
| 664 | if ( 0 === $posted_forum_id ) { |
| 665 | bbp_add_error( 'bbp_topic_forum_id', __( '<strong>Error</strong>: Forum ID is missing.', 'bbpress' ) ); |
| 666 | return 0; |
| 667 | |
| 668 | // Forum id is a negative number |
| 669 | } elseif ( 0 > $posted_forum_id ) { |
| 670 | bbp_add_error( 'bbp_topic_forum_id', __( '<strong>Error</strong>: Forum ID cannot be a negative number.', 'bbpress' ) ); |
| 671 | return 0; |
| 672 | |
| 673 | // Forum does not exist |
| 674 | } elseif ( ! bbp_get_forum( $posted_forum_id ) ) { |
| 675 | bbp_add_error( 'bbp_topic_forum_id', __( '<strong>Error</strong>: Forum does not exist.', 'bbpress' ) ); |
| 676 | return 0; |
| 677 | |
| 678 | // Use the POST'ed forum id |
| 679 | } else { |
| 680 | $forum_id = $posted_forum_id; |
| 681 | } |
| 682 | } |
| 683 | } |
| 684 | |
| 685 | // Forum exists |
| 686 | if ( ! empty( $forum_id ) ) { |
| 687 | |
| 688 | // Forum is a category |
| 689 | if ( bbp_is_forum_category( $forum_id ) ) { |
| 690 | bbp_add_error( 'bbp_new_topic_forum_category', __( '<strong>Error</strong>: This forum is a category. No topics can be created in this forum.', 'bbpress' ) ); |
| 691 | return 0; |
| 692 | |
| 693 | // Forum is not a category |
| 694 | } else { |
| 695 | |
| 696 | // Forum is closed and user cannot access |
| 697 | if ( bbp_is_forum_closed( $forum_id ) && ! current_user_can( 'edit_forum', $forum_id ) ) { |
| 698 | bbp_add_error( 'bbp_new_topic_forum_closed', __( '<strong>Error</strong>: This forum has been closed to new topics.', 'bbpress' ) ); |
| 699 | return 0; |
| 700 | } |
| 701 | |
| 702 | // Forum is private and user cannot access |
| 703 | if ( bbp_is_forum_private( $forum_id ) && ! current_user_can( 'read_forum', $forum_id ) ) { |
| 704 | bbp_add_error( 'bbp_new_topic_forum_private', __( '<strong>Error</strong>: This forum is private and you do not have the capability to read or create new topics in it.', 'bbpress' ) ); |
| 705 | return 0; |
| 706 | |
| 707 | // Forum is hidden and user cannot access |
| 708 | } elseif ( bbp_is_forum_hidden( $forum_id ) && ! current_user_can( 'read_forum', $forum_id ) ) { |
| 709 | bbp_add_error( 'bbp_new_topic_forum_hidden', __( '<strong>Error</strong>: This forum is hidden and you do not have the capability to read or create new topics in it.', 'bbpress' ) ); |
| 710 | return 0; |
| 711 | } |
| 712 | } |
| 713 | } |
| 714 | |
| 715 | return $forum_id; |
| 716 | } |
| 717 | |
| 718 | /** |
| 719 | * Create and save the topic to db |
| 720 | * @return boolean |
| 721 | */ |
| 722 | public function save() { |
| 723 | |
| 724 | // Define local variable(s) |
| 725 | $view_all = false; |
| 726 | $anonymous_data = []; |
| 727 | $topic_author = 0; |
| 728 | $terms = [ bbp_get_topic_tag_tax_id() => [] ]; |
| 729 | |
| 730 | // User is anonymous |
| 731 | if ( bbp_is_anonymous() ) { |
| 732 | $anonymous_data = $this->get_anonymous_data(); |
| 733 | |
| 734 | // User is logged in |
| 735 | } else { |
| 736 | $topic_author = $this->get_topic_author_id(); |
| 737 | if ( empty( $topic_author ) ) { |
| 738 | return false; |
| 739 | } |
| 740 | |
| 741 | // Remove kses filters from title and content for capable users and if the nonce is verified |
| 742 | if ( current_user_can( 'unfiltered_html' ) && ! empty( $this->data['_bbp_unfiltered_html_topic'] ) && wp_create_nonce( 'bbp-unfiltered-html-topic_new' ) === $this->data['_bbp_unfiltered_html_topic'] ) { |
| 743 | remove_filter( 'bbp_new_topic_pre_title', 'wp_filter_kses' ); |
| 744 | remove_filter( 'bbp_new_topic_pre_content', 'bbp_encode_bad', 10 ); |
| 745 | remove_filter( 'bbp_new_topic_pre_content', 'bbp_filter_kses', 30 ); |
| 746 | } |
| 747 | } |
| 748 | |
| 749 | $topic_title = $this->get_topic_title(); |
| 750 | if ( empty( $topic_title ) ) { |
| 751 | return false; |
| 752 | } |
| 753 | |
| 754 | $topic_content = $this->get_topic_content(); |
| 755 | if ( empty( $topic_content ) ) { |
| 756 | return false; |
| 757 | } |
| 758 | |
| 759 | $forum_id = $this->get_forum_id(); |
| 760 | if ( empty( $forum_id ) ) { |
| 761 | return false; |
| 762 | } |
| 763 | |
| 764 | /** Topic Flooding ********************************************************/ |
| 765 | |
| 766 | if ( ! bbp_check_for_flood( $anonymous_data, $topic_author ) ) { |
| 767 | bbp_add_error( 'bbp_topic_flood', __( '<strong>Error</strong>: Slow down; you move too fast.', 'bbpress' ) ); |
| 768 | return false; |
| 769 | } |
| 770 | |
| 771 | /** Topic Duplicate *******************************************************/ |
| 772 | |
| 773 | $dupe_args = array( |
| 774 | 'post_type' => bbp_get_topic_post_type(), |
| 775 | 'post_author' => $topic_author, |
| 776 | 'post_content' => $topic_content, |
| 777 | 'post_parent' => $forum_id, |
| 778 | 'anonymous_data' => $anonymous_data, |
| 779 | ); |
| 780 | |
| 781 | if ( ! bbp_check_for_duplicate( $dupe_args ) ) { |
| 782 | bbp_add_error( 'bbp_topic_duplicate', __( '<strong>Error</strong>: Duplicate topic detected; it looks as though you’ve already said that.', 'bbpress' ) ); |
| 783 | return false; |
| 784 | } |
| 785 | |
| 786 | /** Topic Bad Words *******************************************************/ |
| 787 | |
| 788 | if ( ! bbp_check_for_moderation( $anonymous_data, $topic_author, $topic_title, $topic_content, true ) ) { |
| 789 | bbp_add_error( 'bbp_topic_moderation', __( '<strong>Error</strong>: Your topic cannot be created at this time.', 'bbpress' ) ); |
| 790 | return false; |
| 791 | } |
| 792 | |
| 793 | /** Topic Status **********************************************************/ |
| 794 | |
| 795 | // Get available topic statuses |
| 796 | $topic_statuses = bbp_get_topic_statuses(); |
| 797 | |
| 798 | // Default to published |
| 799 | $topic_status = bbp_get_public_status_id(); |
| 800 | |
| 801 | // Maybe force into pending |
| 802 | if ( ! bbp_check_for_moderation( $anonymous_data, $topic_author, $topic_title, $topic_content ) ) { |
| 803 | $topic_status = bbp_get_pending_status_id(); |
| 804 | |
| 805 | // Check for possible posted topic status |
| 806 | } elseif ( ! empty( $this->data['bbp_topic_status'] ) && in_array( $this->data['bbp_topic_status'], array_keys( $topic_statuses ), true ) ) { |
| 807 | |
| 808 | // Allow capable users to explicitly override the status |
| 809 | if ( current_user_can( 'moderate', $forum_id ) ) { |
| 810 | $topic_status = sanitize_key( $this->data['bbp_topic_status'] ); |
| 811 | |
| 812 | // Not capable |
| 813 | } else { |
| 814 | bbp_add_error( 'bbp_new_topic_status', __( '<strong>Error</strong>: You do not have permission to do that.', 'bbpress' ) ); |
| 815 | return false; |
| 816 | } |
| 817 | } |
| 818 | |
| 819 | /** Topic Tags ************************************************************/ |
| 820 | |
| 821 | if ( bbp_allow_topic_tags() && ! empty( $this->data['bbp_topic_tags'] ) ) { |
| 822 | |
| 823 | // Escape tag input |
| 824 | $terms = sanitize_text_field( $this->data['bbp_topic_tags'] ); |
| 825 | |
| 826 | // Explode by comma |
| 827 | if ( strstr( $terms, ',' ) ) { |
| 828 | $terms = explode( ',', $terms ); |
| 829 | } |
| 830 | |
| 831 | // Add topic tag ID as main key |
| 832 | $terms = array( bbp_get_topic_tag_tax_id() => $terms ); |
| 833 | } |
| 834 | |
| 835 | /** Additional Actions (Before Save) **************************************/ |
| 836 | |
| 837 | do_action( 'bbp_new_topic_pre_extras', $forum_id ); |
| 838 | |
| 839 | // Bail if errors |
| 840 | if ( bbp_has_errors() ) { |
| 841 | return false; |
| 842 | } |
| 843 | |
| 844 | /** No Errors *************************************************************/ |
| 845 | |
| 846 | // Add the content of the form to $topic_data as an array. |
| 847 | // Just in time manipulation of topic data before being created |
| 848 | $topic_data = apply_filters( |
| 849 | 'bbp_new_topic_pre_insert', |
| 850 | [ |
| 851 | 'post_author' => $topic_author, |
| 852 | 'post_title' => $topic_title, |
| 853 | 'post_content' => $topic_content, |
| 854 | 'post_status' => $topic_status, |
| 855 | 'post_parent' => $forum_id, |
| 856 | 'post_type' => bbp_get_topic_post_type(), |
| 857 | 'tax_input' => $terms, |
| 858 | 'comment_status' => 'closed', |
| 859 | ] |
| 860 | ); |
| 861 | |
| 862 | // Insert topic |
| 863 | $topic_id = wp_insert_post( $topic_data, true ); |
| 864 | $this->id = $topic_id; |
| 865 | |
| 866 | /** No Errors *************************************************************/ |
| 867 | |
| 868 | if ( ! empty( $topic_id ) && ! is_wp_error( $topic_id ) ) { |
| 869 | |
| 870 | /** Close Check *******************************************************/ |
| 871 | |
| 872 | // If the topic is closed, close it properly |
| 873 | if ( ( get_post_field( 'post_status', $topic_id ) === bbp_get_closed_status_id() ) || ( $topic_data['post_status'] === bbp_get_closed_status_id() ) ) { |
| 874 | |
| 875 | // Close the topic |
| 876 | bbp_close_topic( $topic_id ); |
| 877 | } |
| 878 | |
| 879 | /** Trash Check *******************************************************/ |
| 880 | |
| 881 | // If the forum is trash, or the topic_status is switched to |
| 882 | // trash, trash the topic properly |
| 883 | if ( ( get_post_field( 'post_status', $forum_id ) === bbp_get_trash_status_id() ) || ( $topic_data['post_status'] === bbp_get_trash_status_id() ) ) { |
| 884 | |
| 885 | // Trash the topic |
| 886 | wp_trash_post( $topic_id ); |
| 887 | |
| 888 | // Force view=all |
| 889 | $view_all = true; |
| 890 | } |
| 891 | |
| 892 | /** Spam Check ********************************************************/ |
| 893 | |
| 894 | // If the topic is spam, officially spam this topic |
| 895 | if ( $topic_data['post_status'] === bbp_get_spam_status_id() ) { |
| 896 | add_post_meta( $topic_id, '_bbp_spam_meta_status', bbp_get_public_status_id() ); |
| 897 | |
| 898 | // Force view=all |
| 899 | $view_all = true; |
| 900 | } |
| 901 | |
| 902 | /** Update counts, etc... *********************************************/ |
| 903 | |
| 904 | do_action( 'bbp_new_topic', $topic_id, $forum_id, $anonymous_data, $topic_author ); |
| 905 | |
| 906 | /** Additional Actions (After Save) ***********************************/ |
| 907 | |
| 908 | do_action( 'bbp_new_topic_post_extras', $topic_id ); |
| 909 | |
| 910 | // If it is not the bbp frontend we do not need to redirect. |
| 911 | if ( ! $this->should_redirect_after ) { |
| 912 | return true; |
| 913 | } |
| 914 | |
| 915 | /** Redirect **********************************************************/ |
| 916 | |
| 917 | // Redirect to |
| 918 | $redirect_to = bbp_get_redirect_to(); |
| 919 | |
| 920 | // Get the topic URL |
| 921 | $redirect_url = bbp_get_topic_permalink( $topic_id, $redirect_to ); |
| 922 | |
| 923 | // Add view all? |
| 924 | if ( bbp_get_view_all() || ! empty( $view_all ) ) { |
| 925 | |
| 926 | // User can moderate, so redirect to topic with view all set |
| 927 | if ( current_user_can( 'moderate', $topic_id ) ) { |
| 928 | $redirect_url = bbp_add_view_all( $redirect_url ); |
| 929 | |
| 930 | // User cannot moderate, so redirect to forum |
| 931 | } else { |
| 932 | $redirect_url = bbp_get_forum_permalink( $forum_id ); |
| 933 | } |
| 934 | } |
| 935 | |
| 936 | // Allow to be filtered |
| 937 | $redirect_url = apply_filters( 'bbp_new_topic_redirect_to', $redirect_url, $redirect_to, $topic_id ); |
| 938 | |
| 939 | /** Successful Save ***************************************************/ |
| 940 | |
| 941 | // Redirect back to new topic |
| 942 | bbp_redirect( $redirect_url ); |
| 943 | |
| 944 | /** Errors ****************************************************************/ |
| 945 | |
| 946 | // WP_Error |
| 947 | } elseif ( is_wp_error( $topic_id ) ) { |
| 948 | /* translators: 1: Error message */ |
| 949 | bbp_add_error( 'bbp_topic_error', sprintf( __( '<strong>Error</strong>: The following problem(s) occurred: %s', 'bbpress' ), $topic_id->get_error_message() ) ); |
| 950 | return false; |
| 951 | // Generic error |
| 952 | } else { |
| 953 | bbp_add_error( 'bbp_topic_error', __( '<strong>Error</strong>: The topic was not created.', 'bbpress' ) ); |
| 954 | return false; |
| 955 | } |
| 956 | } |
| 957 | } |
| 958 | endif; // BBP_Topic |
| 959 | |