Make WordPress Core

Changeset 32523


Ignore:
Timestamp:
05/21/2015 06:42:49 PM (11 years ago)
Author:
boonebgorges
Message:

Support multiple post types in count_user_posts() and other functions that use get_posts_by_author_sql().

Props nikonratm.
Fixes #32243.

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/post.php

    r32355 r32523  
    53285328 * @since 2.2.0
    53295329 *
    5330  * @param string $post_type Post type. Currently only supports 'post' or 'page'.
     5330 * @param string|array $post_type Array or comma-separated string of post types.
     5331 *                                Currently only supports 'post' or 'page'.
    53315332 * @return string SQL code that can be added to a where clause.
    53325333 */
     
    53395340 *
    53405341 * @since 3.0.0
     5342 * @since 4.3.0 Introduced the ability to pass multiple post types to `$post_type`.
    53415343 *
    53425344 * @see get_private_posts_cap_sql()
    53435345 *
    5344  * @param string $post_type   Post type.
    5345  * @param bool   $full        Optional. Returns a full WHERE statement instead of just
    5346  *                            an 'andalso' term. Default true.
    5347  * @param int    $post_author Optional. Query posts having a single author ID. Default null.
    5348  * @param bool   $public_only Optional. Only return public posts. Skips cap checks for
    5349  *                            $current_user.  Default false.
     5346 * @param array|string   $post_type   Array or comma-separated list of post type(s).
     5347 * @param bool           $full        Optional. Returns a full WHERE statement instead of just
     5348 *                                    an 'andalso' term. Default true.
     5349 * @param int            $post_author Optional. Query posts having a single author ID. Default null.
     5350 * @param bool           $public_only Optional. Only return public posts. Skips cap checks for
     5351 *                                    $current_user.  Default false.
    53505352 * @return string SQL WHERE code that can be added to a query.
    53515353 */
     
    53535355        global $wpdb;
    53545356
    5355         // Private posts.
    5356         $post_type_obj = get_post_type_object( $post_type );
    5357         if ( ! $post_type_obj )
    5358                 return $full ? 'WHERE 1 = 0' : ' 1 = 0 ';
    5359 
    5360         /**
    5361          * Filter the capability to read private posts for a custom post type
    5362          * when generating SQL for getting posts by author.
    5363          *
    5364          * @since 2.2.0
    5365          * @deprecated 3.2.0 The hook transitioned from "somewhat useless" to "totally useless".
    5366          *
    5367          * @param string $cap Capability.
    5368          */
    5369         if ( ! $cap = apply_filters( 'pub_priv_sql_capability', '' ) ) {
    5370                 $cap = $post_type_obj->cap->read_private_posts;
    5371         }
    5372 
    5373         $sql = $wpdb->prepare( 'post_type = %s', $post_type );
     5357        if ( is_array( $post_type ) ) {
     5358                $post_types = $post_type;
     5359        } else {
     5360                $post_types = preg_split( '/[\s,]+/', $post_type );
     5361        }
     5362
     5363        $post_type_clauses = array();
     5364        foreach ( $post_types as $post_type ) {
     5365                $post_type_obj = get_post_type_object( $post_type );
     5366                if ( ! $post_type_obj ) {
     5367                        continue;
     5368                }
     5369
     5370                /**
     5371                 * Filter the capability to read private posts for a custom post type
     5372                 * when generating SQL for getting posts by author.
     5373                 *
     5374                 * @since 2.2.0
     5375                 * @deprecated 3.2.0 The hook transitioned from "somewhat useless" to "totally useless".
     5376                 *
     5377                 * @param string $cap Capability.
     5378                 */
     5379                if ( ! $cap = apply_filters( 'pub_priv_sql_capability', '' ) ) {
     5380                        $cap = current_user_can( $post_type_obj->cap->read_private_posts );
     5381                }
     5382
     5383                // Only need to check the cap if $public_only is false.
     5384                $post_status_sql = "post_status = 'publish'";
     5385                if ( false === $public_only ) {
     5386                        if ( $cap ) {
     5387                                // Does the user have the capability to view private posts? Guess so.
     5388                                $post_status_sql .= " OR post_status = 'private'";
     5389                        } elseif ( is_user_logged_in() ) {
     5390                                // Users can view their own private posts.
     5391                                $id = get_current_user_id();
     5392                                if ( null === $post_author || ! $full ) {
     5393                                        $post_status_sql .= " OR post_status = 'private' AND post_author = $id";
     5394                                } elseif ( $id == (int) $post_author ) {
     5395                                        $post_status_sql .= " OR post_status = 'private'";
     5396                                } // else none
     5397                        } // else none
     5398                }
     5399
     5400                $post_type_clauses[] = "( post_type = '" . $post_type . "' AND ( $post_status_sql ) )";
     5401        }
     5402
     5403        if ( empty( $post_type_clauses ) ) {
     5404                return $full ? 'WHERE 1 = 0' : '1 = 0';
     5405        }
     5406
     5407        $sql = '( '. implode( ' OR ', $post_type_clauses ) . ' )';
    53745408
    53755409        if ( null !== $post_author ) {
    53765410                $sql .= $wpdb->prepare( ' AND post_author = %d', $post_author );
    53775411        }
    5378 
    5379         // Only need to check the cap if $public_only is false.
    5380         $post_status_sql = "post_status = 'publish'";
    5381         if ( false === $public_only ) {
    5382                 if ( current_user_can( $cap ) ) {
    5383                         // Does the user have the capability to view private posts? Guess so.
    5384                         $post_status_sql .= " OR post_status = 'private'";
    5385                 } elseif ( is_user_logged_in() ) {
    5386                         // Users can view their own private posts.
    5387                         $id = get_current_user_id();
    5388                         if ( null === $post_author || ! $full ) {
    5389                                 $post_status_sql .= " OR post_status = 'private' AND post_author = $id";
    5390                         } elseif ( $id == (int) $post_author ) {
    5391                                 $post_status_sql .= " OR post_status = 'private'";
    5392                         } // else none
    5393                 } // else none
    5394         }
    5395 
    5396         $sql .= " AND ($post_status_sql)";
    53975412
    53985413        if ( $full ) {
  • trunk/src/wp-includes/user.php

    r32207 r32523  
    252252 * @since 3.0.0
    253253 * @since 4.1.0 Added `$post_type` argument.
     254 * @since 4.3.0 Added `$public_only` argument.
    254255 *
    255256 * @global wpdb $wpdb WordPress database object for queries.
    256257 *
    257  * @param int    $userid    User ID.
    258  * @param string $post_type Optional. Post type to count the number of posts for. Default 'post'.
     258 * @param int          $userid      User ID.
     259 * @param array|string $post_type   Optional. Post type(s) to count the number of posts for. Default 'post'.
     260 * @param bool         $public_only Optional. Only return counts for public posts. Defaults to false.
    259261 * @return int Number of posts the user has written in this post type.
    260262 */
    261 function count_user_posts( $userid, $post_type = 'post' ) {
     263function count_user_posts( $userid, $post_type = 'post', $public_only = false ) {
    262264        global $wpdb;
    263265
    264         $where = get_posts_by_author_sql( $post_type, true, $userid );
     266        $where = get_posts_by_author_sql( $post_type, true, $userid, $public_only );
    265267
    266268        $count = $wpdb->get_var( "SELECT COUNT(*) FROM $wpdb->posts $where" );
     
    271273         * @since 2.7.0
    272274         * @since 4.1.0 Added `$post_type` argument.
    273          *
    274          * @param int    $count     The user's post count.
    275          * @param int    $userid    User ID.
    276          * @param string $post_type Post type to count the number of posts for.
     275         * @since 4.3.0 Added `$public_only` argument.
     276         *
     277         * @param int          $count       The user's post count.
     278         * @param int          $userid      User ID.
     279         * @param string|array $post_types  Post types to count the number of posts for.
     280         * @param bool         $public_only Whether to limit counted posts to public posts.
    277281         */
    278282        return apply_filters( 'get_usernumposts', $count, $userid, $post_type );
     
    284288 * @since 3.0.0
    285289 *
    286  * @param array $users Array of user IDs.
    287  * @param string $post_type Optional. Post type to check. Defaults to post.
    288  * @param bool $public_only Optional. Only return counts for public posts.  Defaults to false.
     290 * @param array        $users      Array of user IDs.
     291 * @param string|array $post_type   Optional. Array or comma-separated list of post types to check. Defaults to 'post'.
     292 * @param bool         $public_only Optional. Only return counts for public posts.  Defaults to false.
    289293 * @return array Amount of posts each user has written.
    290294 */
  • trunk/tests/phpunit/tests/post/getPostsByAuthorSql.php

    r31653 r32523  
    1919                $maybe_string = get_posts_by_author_sql( 'non_existent_post_type' );
    2020                $this->assertContains( '1 = 0', $maybe_string );
     21        }
     22
     23        public function test_multiple_post_types(){
     24                register_post_type( 'foo' );
     25                register_post_type( 'bar' );
     26
     27                $maybe_string = get_posts_by_author_sql( 'foo,bar' );
     28                $this->assertContains( "post_type = 'foo'", $maybe_string );
     29                $this->assertContains( "post_type = 'bar'", $maybe_string );
     30
     31                _unregister_post_type( 'foo' );
     32                _unregister_post_type( 'bar' );
    2133        }
    2234
     
    113125                wp_set_current_user( $current_user );
    114126        }
     127
     128        public function test_user_has_access_only_to_private_posts_for_certain_post_types(){
     129                register_post_type( 'foo', array( 'capabilities' => array( 'read_private_posts' => 'read_private_foo' ) )  );
     130                register_post_type( 'bar', array( 'capabilities' => array( 'read_private_posts' => 'read_private_bar' ) ) );
     131                register_post_type( 'baz', array( 'capabilities' => array( 'read_private_posts' => 'read_private_baz' ) ) );
     132                $current_user = get_current_user_id();
     133                $u = $this->factory->user->create( array( 'role' => 'editor' ) );
     134                $editor_role = get_role('editor');
     135                $editor_role->add_cap( 'read_private_baz' );
     136                wp_set_current_user( $u );
     137
     138                $maybe_string = get_posts_by_author_sql( 'foo,bar,baz' );
     139                $this->assertNotContains( "post_type = 'foo' AND ( post_status = 'publish' OR post_status = 'private' )", $maybe_string );
     140                $this->assertNotContains( "post_type = 'bar' AND ( post_status = 'publish' OR post_status = 'private' )", $maybe_string );
     141                $this->assertContains( "post_type = 'baz' AND ( post_status = 'publish' OR post_status = 'private' )", $maybe_string );
     142
     143                _unregister_post_type( 'foo' );
     144                _unregister_post_type( 'bar' );
     145                _unregister_post_type( 'baz' );
     146                wp_set_current_user( $current_user );
     147        }
    115148}
  • trunk/tests/phpunit/tests/user/countUserPosts.php

    r31622 r32523  
    7979                $this->assertEquals( 3, count_user_posts( self::$user_id, 'wptests_pt' ) );
    8080        }
     81
     82        /**
     83         * @ticket 32243
     84         */
     85        public function test_count_user_posts_with_multiple_post_types() {
     86                $this->assertEquals( 7, count_user_posts( self::$user_id, array( 'wptests_pt', 'post' ) ) );
     87        }
     88
     89        /**
     90         * @ticket 32243
     91         */
     92        public function test_count_user_posts_should_ignore_non_existent_post_types() {
     93                $this->assertEquals( 4, count_user_posts( self::$user_id, array( 'foo', 'post' ) ) );
     94        }
    8195}
Note: See TracChangeset for help on using the changeset viewer.