Make WordPress Core

Changeset 32523


Ignore:
Timestamp:
05/21/2015 06:42:49 PM (9 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.