Skip to:
Content

bbPress.org

Changeset 8058


Ignore:
Timestamp:
10/17/2026 05:35:45 AM (6 days ago)
Author:
johnjamesjacoby
Message:

Common: Inherit forum password requirements.

Extend WordPress's post-password check to bbPress forums, topics, and replies so Core-rendered content respects password-protected ancestors. Reuse the existing ancestor lookup with a per-post re-entry guard to preserve exact protected-post IDs, password cookies, and third-party filter behavior.

Add regression coverage for archive and search loops, user roles, password cookies, and nested password checks.

In branches/2.6, for 2.6.21.

See #2453.

Location:
branches/2.6
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • branches/2.6/src/includes/common/template.php

    r7986 r8058  
    517517 */
    518518function bbp_get_password_required_id( $object_id = 0 ) {
     519        static $checking_id = 0;
     520
    519521        $post     = get_post( $object_id );
    520522        $post_ids = array();
    521523        $forum_id = 0;
     524
     525        // Avoid recursion while checking this post's own password.
     526        if ( ! empty( $post ) && ( $checking_id === (int) $post->ID ) ) {
     527                return 0;
     528        }
    522529
    523530        // Include the object
    … …  
    548555
    549556        // Check the object and its parents
    550         foreach ( array_unique( array_filter( $post_ids ) ) as $post_id ) {
    551                 if ( post_password_required( $post_id ) ) {
    552                         return (int) $post_id;
     557        foreach ( array_unique( array_map( 'intval', array_filter( $post_ids ) ) ) as $post_id ) {
     558                $previous_id = $checking_id;
     559                $checking_id = $post_id;
     560
     561                try {
     562                        $required = post_password_required( $post_id );
     563                } finally {
     564                        $checking_id = $previous_id;
    553565                }
     566
     567                if ( $required ) {
     568                        return $post_id;
     569                }
    554570        }
    555571
    556572        return 0;
     573}
     574
     575/**
     576 * Require passwords inherited from bbPress parent topics and forums.
     577 *
     578 * WordPress checks only the current post. Extend that check for bbPress posts
     579 * so Core content and excerpt rendering preserves the same password boundary
     580 * as bbPress templates.
     581 *
     582 * @since 2.6.21 bbPress (r8058)
     583 *
     584 * @param bool         $required Whether the current post requires a password.
     585 * @param WP_Post|null $post     Post object.
     586 * @return bool Whether the post or a bbPress ancestor requires a password.
     587 */
     588function bbp_filter_post_password_required( $required, $post = null ) {
     589        if ( $required || ! ( $post instanceof WP_Post ) || ! bbp_is_custom_post_type( $post ) ) {
     590                return $required;
     591        }
     592
     593        return ( 0 !== bbp_get_password_required_id( $post ) );
    557594}
    558595
  • branches/2.6/src/includes/core/filters.php

    r8038 r8058  
    7878// Reply title fallback
    7979add_filter( 'the_title', 'bbp_get_reply_title_fallback', 2, 2 );
     80
     81// Inherited post passwords
     82add_filter( 'post_password_required', 'bbp_filter_post_password_required', 10, 2 );
    8083
    8184// Avoid queries & 404s
  • branches/2.6/tests/phpunit/testcases/replies/password-visibility.php

    r7636 r8058  
    88 */
    99class BBP_Tests_Replies_Password_Visibility extends BBP_UnitTestCase {
     10
     11        /**
     12         * @covers ::bbp_filter_post_password_required
     13         */
     14        public function test_password_required_guard_allows_unrelated_nested_checks() {
     15                $forum_id = $this->factory->forum->create(
     16                        array( 'post_password' => 'first-secret' )
     17                );
     18                list( $topic_id, $reply_id ) = $this->create_reply_in_forum( $forum_id );
     19
     20                $other_forum_id = $this->factory->forum->create(
     21                        array( 'post_password' => 'second-secret' )
     22                );
     23                list( , $other_reply_id ) = $this->create_reply_in_forum( $other_forum_id );
     24                $nested_password_id = 0;
     25                $filter             = function( $required, $post ) use ( $topic_id, $other_reply_id, &$nested_password_id ) {
     26                        if ( $topic_id === $post->ID ) {
     27                                $nested_password_id = bbp_get_password_required_id( $other_reply_id );
     28                        }
     29
     30                        return $required;
     31                };
     32
     33                add_filter( 'post_password_required', $filter, 20, 2 );
     34
     35                try {
     36                        $this->assertSame( $forum_id, bbp_get_password_required_id( $reply_id ) );
     37                        $this->assertSame( $other_forum_id, $nested_password_id );
     38                } finally {
     39                        remove_filter( 'post_password_required', $filter, 20 );
     40                }
     41        }
     42
     43        /**
     44         * @covers ::bbp_filter_post_password_required
     45         */
     46        public function test_password_required_filter_ignores_missing_post() {
     47                $this->assertFalse( bbp_filter_post_password_required( false, null ) );
     48        }
     49
     50        /**
     51         * @covers ::bbp_filter_post_password_required
     52         */
     53        public function test_core_reply_listings_require_parent_forum_password_for_all_roles() {
     54                $forum_id = $this->factory->forum->create(
     55                        array( 'post_password' => 'forum-secret' )
     56                );
     57                list( , $reply_id ) = $this->create_reply_in_forum(
     58                        $forum_id,
     59                        'Protected core reply marker'
     60                );
     61                $user_ids = array(
     62                        0,
     63                        $this->create_user_without_role(),
     64                        $this->create_user_with_bbp_role( bbp_get_participant_role() ),
     65                        $this->create_user_with_bbp_role( bbp_get_moderator_role() ),
     66                        $this->create_user_with_bbp_role( bbp_get_keymaster_role() ),
     67                );
     68                $cookie     = 'wp-postpass_' . COOKIEHASH;
     69                $old_cookie = isset( $_COOKIE[ $cookie ] ) ? $_COOKIE[ $cookie ] : null;
     70
     71                try {
     72                        foreach ( $user_ids as $user_id ) {
     73                                $this->set_current_user( $user_id );
     74
     75                                foreach ( array( '/?post_type=reply', '/?s=Protected&post_type=reply' ) as $url ) {
     76                                        $this->go_to_without_reregistering_blocks( $url );
     77                                        $this->assertContains( $reply_id, wp_list_pluck( $GLOBALS['wp_query']->posts, 'ID' ) );
     78                                        $this->assertTrue( post_password_required( $reply_id ) );
     79                                        $this->assertStringNotContainsString( 'Protected core reply marker', get_the_content( null, false, $reply_id ) );
     80                                }
     81                        }
     82
     83                        require_once ABSPATH . WPINC . '/class-phpass.php';
     84                        $hasher            = new PasswordHash( 8, true );
     85                        $_COOKIE[ $cookie ] = $hasher->HashPassword( 'forum-secret' );
     86
     87                        $this->set_current_user( 0 );
     88                        $this->assertFalse( post_password_required( $reply_id ) );
     89                        $this->assertStringContainsString( 'Protected core reply marker', get_the_content( null, false, $reply_id ) );
     90                } finally {
     91                        $this->set_current_user( 0 );
     92
     93                        if ( null === $old_cookie ) {
     94                                unset( $_COOKIE[ $cookie ] );
     95                        } else {
     96                                $_COOKIE[ $cookie ] = $old_cookie;
     97                        }
     98                }
     99        }
    10100
    11101        /**
    … …  
    47137                }
    48138        }
     139
     140        private function create_user_without_role() {
     141                $user_id = $this->factory->user->create();
     142                $user    = new WP_User( $user_id );
     143                $user->set_role( '' );
     144
     145                return $user_id;
     146        }
     147
     148        private function create_reply_in_forum( $forum_id, $content = '' ) {
     149                $topic_id = $this->factory->topic->create(
     150                        array(
     151                                'post_parent' => $forum_id,
     152                                'topic_meta'  => array( 'forum_id' => $forum_id ),
     153                        )
     154                );
     155                $reply_id = $this->factory->reply->create(
     156                        array(
     157                                'post_parent'  => $topic_id,
     158                                'post_content' => $content,
     159                                'reply_meta'   => array( 'forum_id' => $forum_id, 'topic_id' => $topic_id ),
     160                        )
     161                );
     162
     163                return array( $topic_id, $reply_id );
     164        }
     165
     166        private function create_user_with_bbp_role( $role ) {
     167                $user_id = $this->factory->user->create();
     168                bbp_set_user_role( $user_id, $role );
     169
     170                return $user_id;
     171        }
     172
     173        private function go_to_without_reregistering_blocks( $url ) {
     174                remove_action( 'bbp_register', 'bbp_register_blocks', 10 );
     175                try {
     176                        $this->go_to( home_url( $url ) );
     177                } finally {
     178                        add_action( 'bbp_register', 'bbp_register_blocks', 10 );
     179                }
     180        }
    49181}
Note: See TracChangeset for help on using the changeset viewer.