Skip to:
Content

bbPress.org

Changeset 6827


Ignore:
Timestamp:
07/05/2018 06:03:38 AM (8 years ago)
Author:
johnjamesjacoby
Message:

Counts: Introduce a cacheable parent/type/status wrapper, filter helpers.

This change introduces a common query function for totalling up all counts by type & status, and caching the results for later usages. By doing this, we can avoid running multiple queries for the same public or non-public counts.

Also uses bbp_number_not_negative() in a few places where negative counts are never allowed.

Location:
trunk/src/includes
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/includes/common/functions.php

    r6814 r6827  
    16101610
    16111611/**
     1612 * Query the database for child counts, grouped by type & status
     1613 *
     1614 * @since 2.6.0 bbPress (r6826)
     1615 *
     1616 * @param int $parent_id
     1617 */
     1618function bbp_get_child_counts( $parent_id = 0 ) {
     1619
     1620    // Create cache key
     1621    $parent_id    = absint( $parent_id );
     1622    $key          = md5( serialize( array( 'parent_id' => $parent_id, 'post_type' => bbp_get_post_types() ) ) );
     1623    $last_changed = wp_cache_get_last_changed( 'bbpress_posts' );
     1624    $cache_key    = "bbp_child_counts:{$key}:{$last_changed}";
     1625
     1626    // Check for cache and set if needed
     1627    $retval = wp_cache_get( $cache_key, 'bbpress_posts' );
     1628    if ( false === $retval ) {
     1629
     1630        // Setup the DB & query
     1631        $bbp_db = bbp_db();
     1632        $sql    = "SELECT
     1633                        p.post_type AS type,
     1634                        p.post_status AS status,
     1635                        COUNT( * ) AS count
     1636                    FROM {$bbp_db->posts} AS p
     1637                        LEFT JOIN {$bbp_db->postmeta} AS pm
     1638                            ON p.ID = pm.post_id
     1639                            AND pm.meta_key = %s
     1640                    WHERE pm.meta_value = %d
     1641                    GROUP BY p.post_status, p.post_type";
     1642
     1643        // Get prepare vars
     1644        $post_type = get_post_type( $parent_id );
     1645        $meta_key  = "_bbp_{$post_type}_id";
     1646
     1647        // Prepare & get results
     1648        $query     = $bbp_db->prepare( $sql, $meta_key, $parent_id );
     1649        $results   = $bbp_db->get_results( $query, ARRAY_A );
     1650
     1651        // Setup return value
     1652        $retval    = wp_list_pluck( $results, 'type', 'type' );
     1653        $statuses  = get_post_stati();
     1654
     1655        // Loop through results
     1656        foreach ( $results as $row ) {
     1657
     1658            // Setup empties
     1659            if ( ! is_array( $retval[ $row['type'] ] ) ) {
     1660                $retval[ $row['type'] ] = array_fill_keys( $statuses, 0 );
     1661            }
     1662
     1663            // Set statuses
     1664            $retval[ $row['type'] ][ $row['status'] ] = bbp_number_not_negative( $row['count'] );
     1665        }
     1666
     1667        // Always cache the results
     1668        wp_cache_set( $cache_key, $retval, 'bbpress_posts' );
     1669    }
     1670
     1671    // Make sure results are INTs
     1672    return (array) apply_filters( 'bbp_get_child_counts', $retval, $parent_id );
     1673}
     1674
     1675/**
     1676 * Filter a list of child counts, from `bbp_get_child_counts()`
     1677 *
     1678 * @since 2.6.0 bbPress (r6826)
     1679 *
     1680 * @param int    $parent_id  ID of post to get child counts from
     1681 * @param array  $types      Optional. An array of post types to filter by
     1682 * @param array  $statuses   Optional. An array of post statuses to filter by
     1683 *
     1684 * @return array A list of objects or object fields.
     1685 */
     1686function bbp_filter_child_counts_list( $parent_id = 0, $types = array( 'post' ), $statuses = array() ) {
     1687
     1688    // Setup local vars
     1689    $retval   = array();
     1690    $types    = array_flip( (array) $types    );
     1691    $statuses = array_flip( (array) $statuses );
     1692    $counts   = bbp_get_child_counts( $parent_id );
     1693
     1694    // Loop through counts by type
     1695    foreach ( $counts as $type => $type_counts ) {
     1696
     1697        // Skip if not this type
     1698        if ( ! isset( $types[ $type ] ) ) {
     1699            continue;
     1700        }
     1701
     1702        // Maybe filter statuses
     1703        if ( ! empty( $statuses ) ) {
     1704            $type_counts = array_intersect_key( $type_counts, $statuses );
     1705        }
     1706
     1707        // Add type counts to return array
     1708        $retval[ $type ] = $type_counts;
     1709    }
     1710
     1711    // Filter & return
     1712    return (array) apply_filters( 'bbp_filter_child_counts_list', $retval, $parent_id, $types, $statuses );
     1713}
     1714
     1715/**
    16121716 * Query the DB and get a count of public children
    16131717 *
     
    16261730    }
    16271731
    1628     // Check the public post status
    1629     $post_status = array( bbp_get_public_status_id() );
    1630 
    1631     // Add closed status if topic post type
    1632     if ( bbp_get_topic_post_type() === $post_type ) {
    1633         $post_status[] = bbp_get_closed_status_id();
    1634     }
    1635 
    1636     $query = new WP_Query( array(
    1637         'fields'         => 'ids',
    1638         'post_parent'    => $parent_id,
    1639         'post_status'    => $post_status,
    1640         'post_type'      => $post_type,
    1641         'posts_per_page' => -1,
    1642 
    1643         // Performance
    1644         'nopaging'               => true,
    1645         'suppress_filters'       => true,
    1646         'update_post_term_cache' => false,
    1647         'update_post_meta_cache' => false,
    1648         'ignore_sticky_posts'    => true,
    1649         'no_found_rows'          => true
    1650     ) );
    1651     $child_count = $query->post_count;
    1652     unset( $query );
     1732    // Which statuses
     1733    switch ( $post_type ) {
     1734
     1735        // Forum
     1736        case bbp_get_forum_post_type() :
     1737            $post_status = array( bbp_get_public_status_id() );
     1738            break;
     1739
     1740        // Topic
     1741        case bbp_get_topic_post_type() :
     1742            $post_status = bbp_get_public_topic_statuses();
     1743            break;
     1744
     1745        // Reply
     1746        case bbp_get_reply_post_type() :
     1747        default :
     1748            $post_status = bbp_get_public_reply_statuses();
     1749            break;
     1750    }
     1751
     1752    // Get counts
     1753    $counts      = bbp_filter_child_counts_list( $parent_id, $post_type, $post_status );
     1754    $child_count = isset( $counts[ $post_type ] )
     1755        ? bbp_number_not_negative( array_sum( array_values( $counts[ $post_type ] ) ) )
     1756        : 0;
    16531757
    16541758    // Filter & return
    16551759    return (int) apply_filters( 'bbp_get_public_child_count', $child_count, $parent_id, $post_type );
     1760}
     1761/**
     1762 * Query the DB and get a count of public children
     1763 *
     1764 * @since 2.0.0 bbPress (r2868)
     1765 * @since 2.6.0 bbPress (r5954) Replace direct queries with WP_Query() objects
     1766 *
     1767 * @param int    $parent_id Parent id.
     1768 * @param string $post_type Post type. Defaults to 'post'.
     1769 * @return int The number of children
     1770 */
     1771function bbp_get_non_public_child_count( $parent_id = 0, $post_type = 'post' ) {
     1772
     1773    // Bail if nothing passed
     1774    if ( empty( $parent_id ) || empty( $post_type ) ) {
     1775        return false;
     1776    }
     1777
     1778    // Which statuses
     1779    switch ( $post_type ) {
     1780
     1781        // Forum
     1782        case bbp_get_forum_post_type() :
     1783            $post_status = array( bbp_get_private_status_id(), bbp_get_hidden_status_id() );
     1784            break;
     1785
     1786        // Topic
     1787        case bbp_get_topic_post_type() :
     1788            $post_status = bbp_get_non_public_topic_statuses();
     1789            break;
     1790
     1791        // Reply
     1792        case bbp_get_reply_post_type() :
     1793        default :
     1794            $post_status = bbp_get_non_public_reply_statuses();
     1795            break;
     1796    }
     1797
     1798    // Get counts
     1799    $counts      = bbp_filter_child_counts_list( $parent_id, $post_type, $post_status );
     1800    $child_count = isset( $counts[ $post_type ] )
     1801        ? bbp_number_not_negative( array_sum( array_values( $counts[ $post_type ] ) ) )
     1802        : 0;
     1803
     1804    // Filter & return
     1805    return (int) apply_filters( 'bbp_get_non_public_child_count', $child_count, $parent_id, $post_type );
    16561806}
    16571807
  • trunk/src/includes/topics/functions.php

    r6793 r6827  
    24712471
    24722472    // Get replies of topic if not passed
    2473     if ( empty( $reply_count ) ) {
    2474         $reply_count = bbp_get_public_child_count( $topic_id, bbp_get_reply_post_type() );
    2475     }
    2476 
    2477     $reply_count = (int) $reply_count;
     2473    $reply_count = empty( $reply_count )
     2474        ? bbp_get_public_child_count( $topic_id, bbp_get_reply_post_type() )
     2475        : (int) $reply_count;
    24782476
    24792477    update_post_meta( $topic_id, '_bbp_reply_count', $reply_count );
     
    25012499
    25022500    // Get replies of topic
    2503     if ( empty( $reply_count ) ) {
    2504         $statuses    = bbp_get_non_public_topic_statuses();
    2505         $post_status = "'" . implode( "','", $statuses ) . "'";
    2506         $bbp_db      = bbp_db();
    2507         $query       = $bbp_db->prepare( "SELECT COUNT(ID) FROM {$bbp_db->posts} WHERE post_parent = %d AND post_status IN ( {$post_status} ) AND post_type = %s", $topic_id, bbp_get_reply_post_type() );
    2508         $reply_count = $bbp_db->get_var( $query );
    2509     }
    2510 
    2511     $reply_count = (int) $reply_count;
     2501    $reply_count = empty( $reply_count )
     2502        ? bbp_get_non_public_child_count( $topic_id, 'reply' )
     2503        : (int) $reply_count;
    25122504
    25132505    update_post_meta( $topic_id, '_bbp_reply_count_hidden', $reply_count );
Note: See TracChangeset for help on using the changeset viewer.