Skip to:
Content

BuddyPress.org

Changeset 13988


Ignore:
Timestamp:
07/27/2024 07:58:27 PM (7 months ago)
Author:
espellcaste
Message:

Activity: Add cache_results flag to the BP_Activity_Activity::get getter.

When performing a request with cache_results, it stops the activity information retrieved from being added to the cache.

See #8552
Closes https://github.com/buddypress/buddypress/pull/343/

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-activity/bp-activity-functions.php

    r13927 r13988  
    18711871 * @since 1.2.0
    18721872 * @since 2.4.0 Introduced the `$fields` parameter.
     1873 * @since 15.0.0 Introduced the `cache_results` parameter.
    18731874 *
    18741875 * @see BP_Activity_Activity::get() For more information on accepted arguments
     
    18991900            'in'                => false,        // Comma-separated list or array of activity IDs to which you want to limit the query.
    19001901            'spam'              => 'ham_only',   // 'ham_only' (default), 'spam_only' or 'all'.
     1902            'cache_results'     => true,
    19011903            'update_meta_cache' => true,
    19021904            'count_total'       => false,
     
    19381940            'in'                => $r['in'],
    19391941            'spam'              => $r['spam'],
     1942            'cache_results'     => $r['cache_results'],
    19401943            'update_meta_cache' => $r['update_meta_cache'],
    19411944            'count_total'       => $r['count_total'],
     
    19601963 *
    19611964 * @since 1.2.0
     1965 * @since 15.0.0 Introduced the `cache_results` parameter.
    19621966 *
    19631967 * @see BP_Activity_Activity::get() For more information on accepted arguments.
     
    19851989            'sort'              => 'DESC',     // Sort ASC or DESC.
    19861990            'spam'              => 'ham_only', // Retrieve items marked as spam.
     1991            'cache_results'     => true,
    19871992            'update_meta_cache' => true,
    19881993        ),
     
    19992004        'sort'              => $r['sort'],
    20002005        'spam'              => $r['spam'],
     2006        'cache_results'     => $r['cache_results'],
    20012007        'update_meta_cache' => $r['update_meta_cache'],
    20022008    );
  • trunk/src/bp-activity/classes/class-bp-activity-activity.php

    r13897 r13988  
    383383     *     @type bool         $show_hidden       Whether to show items marked hide_sitewide. Default: false.
    384384     *     @type string       $spam              Spam status. Default: 'ham_only'.
     385     *     @type bool         $cache_results     Optional. Whether to cache activity information. Default true.
    385386     *     @type bool         $update_meta_cache Whether to pre-fetch metadata for queried activity items. Default: true.
    386387     *     @type string|bool  $count_total       If true, an additional DB query is run to count the total activity items
     
    451452                'show_hidden'       => false,           // Show items marked hide_sitewide.
    452453                'spam'              => 'ham_only',      // Spam status.
    453                 'update_meta_cache' => true,            // Whether or not to update meta cache.
    454                 'count_total'       => false,           // Whether or not to use count_total.
     454                'cache_results'     => true,            // Whether to cache activity information.
     455                'update_meta_cache' => true,            // Whether to update meta cache.
     456                'count_total'       => false,           // Whether to use count_total.
    455457                'count_total_only'  => false,           // Whether to only get the total count.
    456458            )
     
    494496
    495497        // Regular filtering.
    496         if ( $r['filter'] && $filter_sql = BP_Activity_Activity::get_filter_sql( $r['filter'] ) ) {
     498        if ( $r['filter'] && $filter_sql = self::get_filter_sql( $r['filter'] ) ) {
    497499            $where_conditions['filter_sql'] = $filter_sql;
    498500        }
     
    735737            }
    736738
    737             /*
    738              * Queries that include 'last_activity' are cached separately,
    739              * since they are generally much less long-lived.
    740              */
    741             if ( preg_match( '/a\.type NOT IN \([^\)]*\'last_activity\'[^\)]*\)/', $activity_sql ) ) {
    742                 $cache_group = 'bp_activity';
    743             } else {
    744                 $cache_group = 'bp_activity_with_last_activity';
    745             }
    746 
    747739            $activities = $wpdb->get_results( $activity_sql );
    748740
     
    758750                $activities[ $i ]->is_spam           = (int) $ac->is_spam;
    759751            }
    760 
    761752        } elseif ( ! $only_get_count ) {
    762753            // Query first for activity IDs.
     
    779770            $activity_ids_sql = apply_filters( 'bp_activity_paged_activities_sql', $activity_ids_sql, $r );
    780771
    781             /*
    782              * Queries that include 'last_activity' are cached separately,
    783              * since they are generally much less long-lived.
    784              */
    785             if ( preg_match( '/a\.type NOT IN \([^\)]*\'last_activity\'[^\)]*\)/', $activity_ids_sql ) ) {
    786                 $cache_group = 'bp_activity';
     772            if ( $r['cache_results'] ) {
     773                /*
     774                 * Queries that include 'last_activity' are cached separately,
     775                 * since they are generally much less long-lived.
     776                 */
     777                $cache_group = ( preg_match( '/a\.type NOT IN \([^\)]*\'last_activity\'[^\)]*\)/', $activity_ids_sql ) )
     778                    ? 'bp_activity'
     779                    : 'bp_activity_with_last_activity';
     780
     781                $cached = bp_core_get_incremented_cache( $activity_ids_sql, $cache_group );
     782                if ( false === $cached ) {
     783                    $activity_ids = $wpdb->get_col( $activity_ids_sql );
     784                    bp_core_set_incremented_cache( $activity_ids_sql, $cache_group, $activity_ids );
     785                } else {
     786                    $activity_ids = $cached;
     787                }
    787788            } else {
    788                 $cache_group = 'bp_activity_with_last_activity';
    789             }
    790 
    791             $cached = bp_core_get_incremented_cache( $activity_ids_sql, $cache_group );
    792             if ( false === $cached ) {
    793789                $activity_ids = $wpdb->get_col( $activity_ids_sql );
    794                 bp_core_set_incremented_cache( $activity_ids_sql, $cache_group, $activity_ids );
    795             } else {
    796                 $activity_ids = $cached;
    797790            }
    798791
     
    808801                $activities = array_map( 'intval', $activity_ids );
    809802            } else {
    810                 $activities = self::get_activity_data( $activity_ids );
     803                $activities = self::get_activity_data( $activity_ids, $r['cache_results'] );
    811804            }
    812805        }
     
    818811            // Get activity meta.
    819812            $activity_ids = array();
    820             foreach ( (array) $activities as $activity ) {
     813            foreach ( $activities as $activity ) {
    821814                $activity_ids[] = $activity->id;
    822815            }
     
    826819            }
    827820
    828             if ( $activities && $r['display_comments'] ) {
    829                 $activities = BP_Activity_Activity::append_comments( $activities, $r['spam'] );
     821            if ( $r['display_comments'] ) {
     822                $activities = self::append_comments( $activities, $r['spam'] );
    830823            }
    831824
    832825            // Pre-fetch data associated with activity users and other objects.
    833             BP_Activity_Activity::prefetch_object_data( $activities );
     826            self::prefetch_object_data( $activities );
    834827
    835828            // Generate action strings.
    836             $activities = BP_Activity_Activity::generate_action_strings( $activities );
     829            $activities = self::generate_action_strings( $activities );
    837830        }
    838831
     
    841834        // Only query the count total if requested.
    842835        if ( ! empty( $r['count_total'] ) || $only_get_count ) {
     836            $total_activities_sql = "SELECT count(DISTINCT a.id) FROM {$bp->activity->table_name} a {$join_sql} {$where_sql}";
     837
    843838            /**
    844839             * Filters the total activities MySQL statement.
     
    846841             * @since 1.5.0
    847842             *
    848              * @param string $value    MySQL statement used to query for total activities.
    849              * @param string $where_sql MySQL WHERE statement portion.
    850              * @param string $sort      Sort direction for query.
     843             * @param string $total_activities_sql MySQL statement used to query for total activities.
     844             * @param string $where_sql            MySQL WHERE statement portion.
     845             * @param string $sort                 Sort direction for query.
    851846             */
    852             $total_activities_sql = apply_filters( 'bp_activity_total_activities_sql', "SELECT count(DISTINCT a.id) FROM {$bp->activity->table_name} a {$join_sql} {$where_sql}", $where_sql, $sort );
     847            $total_activities_sql = apply_filters( 'bp_activity_total_activities_sql', $total_activities_sql, $where_sql, $sort );
    853848
    854849            /*
     
    856851             * since they are generally much less long-lived.
    857852             */
    858             if ( preg_match( '/a\.type NOT IN \([^\)]*\'last_activity\'[^\)]*\)/', $total_activities_sql ) ) {
    859                 $cache_group = 'bp_activity';
     853            $cache_group = ( preg_match( '/a\.type NOT IN \([^\)]*\'last_activity\'[^\)]*\)/', $total_activities_sql ) )
     854                ? 'bp_activity'
     855                : 'bp_activity_with_last_activity';
     856
     857            if ( $r['cache_results'] ) {
     858                $cached = bp_core_get_incremented_cache( $total_activities_sql, $cache_group );
     859                if ( false === $cached ) {
     860                    $total_activities = $wpdb->get_var( $total_activities_sql );
     861                    bp_core_set_incremented_cache( $total_activities_sql, $cache_group, $total_activities );
     862                } else {
     863                    $total_activities = $cached;
     864                }
    860865            } else {
    861                 $cache_group = 'bp_activity_with_last_activity';
    862             }
    863 
    864             $cached = bp_core_get_incremented_cache( $total_activities_sql, $cache_group );
    865             if ( false === $cached ) {
    866866                $total_activities = $wpdb->get_var( $total_activities_sql );
    867                 bp_core_set_incremented_cache( $total_activities_sql, $cache_group, $total_activities );
    868             } else {
    869                 $total_activities = $cached;
    870867            }
    871868
    872869            // If $max is set, only return up to the max results.
    873             if ( ! empty( $r['max'] ) ) {
    874                 if ( (int) $total_activities > (int) $r['max'] ) {
    875                     $total_activities = $r['max'];
    876                 }
     870            if ( ! empty( $r['max'] ) && ( (int) $total_activities > (int) $r['max'] ) ) {
     871                $total_activities = $r['max'];
    877872            }
    878873
     
    887882     *
    888883     * @since 2.0.0
     884     * @since 15.0.0 Added the `$cache_results` parameter.
    889885     *
    890886     * @global wpdb $wpdb WordPress database object.
    891887     *
    892888     * @param array $activity_ids Array of activity IDs.
     889     * @param bool  $cache_results Optional. Whether to cache activity information. Default true.
    893890     * @return array
    894891     */
    895     protected static function get_activity_data( $activity_ids = array() ) {
     892    protected static function get_activity_data( $activity_ids = array(), $cache_results = true ) {
    896893        global $wpdb;
    897894
    898895        // Bail if no activity ID's passed.
    899         if ( empty( $activity_ids ) ) {
     896        if ( empty( $activity_ids ) || ! is_array( $activity_ids ) ) {
    900897            return array();
    901898        }
     
    904901        $bp = buddypress();
    905902
    906         $activities   = array();
    907         $uncached_ids = bp_get_non_cached_ids( $activity_ids, 'bp_activity' );
    908 
    909         // Prime caches as necessary.
    910         if ( ! empty( $uncached_ids ) ) {
    911             // Format the activity ID's for use in the query below.
    912             $uncached_ids_sql = implode( ',', wp_parse_id_list( $uncached_ids ) );
     903        $activities = array();
     904
     905        if ( $cache_results ) {
     906            $uncached_ids = bp_get_non_cached_ids( $activity_ids, 'bp_activity' );
     907
     908            // Prime caches as necessary.
     909            if ( ! empty( $uncached_ids ) ) {
     910                // Format the activity ID's for use in the query below.
     911                $uncached_ids_sql = implode( ',', wp_parse_id_list( $uncached_ids ) );
     912
     913                // Fetch data from activity table.
     914                $queried_activity_data = $wpdb->get_results( "SELECT * FROM {$bp->activity->table_name} WHERE id IN ({$uncached_ids_sql})" );
     915
     916                // Put that data into the placeholders created earlier,
     917                // and add it to the cache.
     918                foreach ( (array) $queried_activity_data as $activity_data ) {
     919                    wp_cache_set( $activity_data->id, $activity_data, 'bp_activity' );
     920                }
     921            }
     922
     923            // Now fetch data from the cache.
     924            foreach ( $activity_ids as $activity_id ) {
     925                // Integer casting.
     926                $activity = wp_cache_get( $activity_id, 'bp_activity' );
     927                if ( ! empty( $activity ) ) {
     928                    $activity->id                = (int) $activity->id;
     929                    $activity->user_id           = (int) $activity->user_id;
     930                    $activity->item_id           = (int) $activity->item_id;
     931                    $activity->secondary_item_id = (int) $activity->secondary_item_id;
     932                    $activity->hide_sitewide     = (int) $activity->hide_sitewide;
     933                    $activity->mptt_left         = (int) $activity->mptt_left;
     934                    $activity->mptt_right        = (int) $activity->mptt_right;
     935                    $activity->is_spam           = (int) $activity->is_spam;
     936                }
     937
     938                $activities[] = $activity;
     939            }
     940        } else {
     941            $activity_ids = implode( ',', wp_parse_id_list( $activity_ids ) );
    913942
    914943            // Fetch data from activity table, preserving order.
    915             $queried_adata = $wpdb->get_results( "SELECT * FROM {$bp->activity->table_name} WHERE id IN ({$uncached_ids_sql})");
    916 
    917             // Put that data into the placeholders created earlier,
    918             // and add it to the cache.
    919             foreach ( (array) $queried_adata as $adata ) {
    920                 wp_cache_set( $adata->id, $adata, 'bp_activity' );
    921             }
    922         }
    923 
    924         // Now fetch data from the cache.
    925         foreach ( $activity_ids as $activity_id ) {
    926             // Integer casting.
    927             $activity = wp_cache_get( $activity_id, 'bp_activity' );
    928             if ( ! empty( $activity ) ) {
     944            $uncached_queried_activity_data = $wpdb->get_results(
     945                "SELECT * FROM {$bp->activity->table_name} WHERE id IN ({$activity_ids}) ORDER BY FIELD( {$bp->activity->table_name}.id, {$activity_ids} )"
     946            );
     947
     948            foreach ( $uncached_queried_activity_data as $activity ) {
    929949                $activity->id                = (int) $activity->id;
    930950                $activity->user_id           = (int) $activity->user_id;
     
    935955                $activity->mptt_right        = (int) $activity->mptt_right;
    936956                $activity->is_spam           = (int) $activity->is_spam;
    937             }
    938 
    939             $activities[] = $activity;
     957
     958                $activities[] = $activity;
     959            }
    940960        }
    941961
    942962        // Then fetch user data.
    943         $user_query = new BP_User_Query( array(
    944             'user_ids'        => wp_list_pluck( $activities, 'user_id' ),
    945             'populate_extras' => false,
    946         ) );
     963        $user_query = new BP_User_Query(
     964            array(
     965                'user_ids'        => wp_list_pluck( $activities, 'user_id' ),
     966                'populate_extras' => false,
     967            )
     968        );
    947969
    948970        // Associated located user data with activity items.
     
    951973            $a_user    = isset( $user_query->results[ $a_user_id ] ) ? $user_query->results[ $a_user_id ] : '';
    952974
    953             if ( !empty( $a_user ) ) {
     975            if ( ! empty( $a_user ) ) {
    954976                $activities[ $a_index ]->user_email    = $a_user->user_email;
    955977                $activities[ $a_index ]->user_nicename = $a_user->user_nicename;
     
    971993     */
    972994    protected static function append_user_fullnames( $activities ) {
    973 
    974995        if ( bp_is_active( 'xprofile' ) && ! empty( $activities ) ) {
    975996            $activity_user_ids = wp_list_pluck( $activities, 'user_id' );
  • trunk/tests/phpunit/testcases/activity/cache.php

    r13149 r13988  
    66 */
    77class BP_Tests_Activity_Cache extends BP_UnitTestCase {
     8
     9    /**
     10     * @ticket BP8552
     11     */
     12    public function test_activity_query_with_ids_cache_results() {
     13        global $wpdb;
     14
     15        self::factory()->activity->create_many( 2 );
     16
     17        // Reset.
     18        $wpdb->num_queries = 0;
     19
     20        $first_query = BP_Activity_Activity::get(
     21            array(
     22                'cache_results' => true,
     23                'fields'        => 'ids',
     24            )
     25        );
     26
     27        $queries_before = get_num_queries();
     28
     29        $second_query = BP_Activity_Activity::get(
     30            array(
     31                'cache_results' => false,
     32                'fields'        => 'ids',
     33            )
     34        );
     35
     36        $queries_after = get_num_queries();
     37
     38        $this->assertNotSame( $queries_before, $queries_after, 'Assert that queries are run' );
     39        $this->assertSame( 2, $queries_after, 'Assert that the uncached query was run' );
     40        $this->assertSameSets( $first_query['activities'], $second_query['activities'], 'Results of the query are expected to match.' );
     41    }
     42
     43    /**
     44     * @ticket BP8552
     45     */
     46    public function test_activity_query_with_count_total_cache_results() {
     47        global $wpdb;
     48
     49        self::factory()->activity->create_many( 2 );
     50
     51        // Reset.
     52        $wpdb->num_queries = 0;
     53
     54        $first_query = BP_Activity_Activity::get(
     55            array(
     56                'cache_results' => true,
     57                'count_total'   => true,
     58            )
     59        );
     60
     61        $queries_before = get_num_queries();
     62
     63        $second_query = BP_Activity_Activity::get(
     64            array(
     65                'cache_results' => false,
     66                'count_total'   => true,
     67            )
     68        );
     69
     70        $queries_after = get_num_queries();
     71
     72        $this->assertNotSame( $queries_before, $queries_after, 'Assert that queries are run' );
     73        $this->assertSame( 9, $queries_after, 'Assert that the uncached query was run' );
     74        $this->assertSame( $first_query['total'], $second_query['total'], 'Results of the query are expected to match.' );
     75    }
     76
     77    /**
     78     * @ticket BP8552
     79     */
     80    public function test_activity_query_with_all_cache_results() {
     81        global $wpdb;
     82
     83        self::factory()->activity->create_many( 2 );
     84
     85        // Reset.
     86        $wpdb->num_queries = 0;
     87
     88        $first_query = BP_Activity_Activity::get(
     89            array( 'cache_results' => true )
     90        );
     91
     92        $queries_before = get_num_queries();
     93
     94        $second_query = BP_Activity_Activity::get(
     95            array( 'cache_results' => false )
     96        );
     97
     98        $queries_after = get_num_queries();
     99
     100        $this->assertNotSame( $queries_before, $queries_after, 'Assert that queries are run' );
     101        $this->assertSame( 7, $queries_after, 'Assert that the uncached query was run' );
     102        $this->assertSameSets(
     103            array_map(
     104                function ( $a ) {
     105                    return $a->id;
     106                },
     107                $first_query['activities']
     108            ),
     109            array_map(
     110                function ( $a ) {
     111                    return $a->id;
     112                },
     113                $second_query['activities']
     114            ),
     115            'Results of the query are expected to match.'
     116        );
     117    }
     118
    8119    /**
    9120     * @group bp_activity_update_meta_cache
Note: See TracChangeset for help on using the changeset viewer.