array(), // Comma-separated list or array of item ids. 'object_type' => '', // Canonical component id: groups, members, etc. 'cache_group' => '', // Cache group. 'meta_table' => '', // Name of the table containing the metadata. 'object_column' => '', // DB column for the object ids (group_id, etc). 'cache_key_prefix' => '', // Prefix to use when creating cache key names. Eg 'bp_groups_groupmeta'. ) ); extract( $r ); if ( empty( $object_ids ) || empty( $object_type ) || empty( $meta_table ) || empty( $cache_group ) ) { return false; } if ( empty( $cache_key_prefix ) ) { $cache_key_prefix = $meta_table; } if ( empty( $object_column ) ) { $object_column = $object_type . '_id'; } if ( ! $cache_group ) { return false; } $object_ids = wp_parse_id_list( $object_ids ); $uncached_ids = bp_get_non_cached_ids( $object_ids, $cache_group ); $cache = array(); // Get meta info. if ( ! empty( $uncached_ids ) ) { $id_list = join( ',', wp_parse_id_list( $uncached_ids ) ); $meta_list = $wpdb->get_results( esc_sql( "SELECT {$object_column}, meta_key, meta_value FROM {$meta_table} WHERE {$object_column} IN ({$id_list})" ), ARRAY_A ); if ( ! empty( $meta_list ) ) { foreach ( $meta_list as $metarow ) { $mpid = intval( $metarow[$object_column] ); $mkey = $metarow['meta_key']; $mval = $metarow['meta_value']; // Force subkeys to be array type. if ( !isset( $cache[$mpid] ) || !is_array( $cache[$mpid] ) ) $cache[$mpid] = array(); if ( !isset( $cache[$mpid][$mkey] ) || !is_array( $cache[$mpid][$mkey] ) ) $cache[$mpid][$mkey] = array(); // Add a value to the current pid/key. $cache[$mpid][$mkey][] = $mval; } } foreach ( $uncached_ids as $uncached_id ) { // Cache empty values as well. if ( ! isset( $cache[ $uncached_id ] ) ) { $cache[ $uncached_id ] = array(); } wp_cache_set( $uncached_id, $cache[ $uncached_id ], $cache_group ); } } return $cache; } /** * Gets a value that has been cached using an incremented key. * * A utility function for use by query methods like BP_Activity_Activity::get(). * * @since 2.7.0 * @see bp_core_set_incremented_cache() * * @param string $key Unique key for the query. Usually a SQL string. * @param string $group Cache group. Eg 'bp_activity'. * @return array|bool False if no cached values are found, otherwise an array of IDs. */ function bp_core_get_incremented_cache( $key, $group ) { $cache_key = bp_core_get_incremented_cache_key( $key, $group ); return wp_cache_get( $cache_key, $group ); } /** * Caches a value using an incremented key. * * An "incremented key" is a cache key that is hashed with a unique incrementor, * allowing for bulk invalidation. * * Use this method when caching data that should be invalidated whenever any * object of a given type is created, updated, or deleted. This usually means * data related to object queries, which can only reliably cached until the * underlying set of objects has been modified. See, eg, BP_Activity_Activity::get(). * * @since 2.7.0 * * @param string $key Unique key for the query. Usually a SQL string. * @param string $group Cache group. Eg 'bp_activity'. * @param array $ids Array of IDs. * @return bool */ function bp_core_set_incremented_cache( $key, $group, $ids ) { $cache_key = bp_core_get_incremented_cache_key( $key, $group ); return wp_cache_set( $cache_key, $ids, $group ); } /** * Delete a value that has been cached using an incremented key. * * A utility function for use by query methods like BP_Activity_Activity::get(). * * @since 3.0.0 * @see bp_core_set_incremented_cache() * * @param string $key Unique key for the query. Usually a SQL string. * @param string $group Cache group. Eg 'bp_activity'. * @return bool True on successful removal, false on failure. */ function bp_core_delete_incremented_cache( $key, $group ) { $cache_key = bp_core_get_incremented_cache_key( $key, $group ); return wp_cache_delete( $cache_key, $group ); } /** * Gets the key to be used when caching a value using an incremented cache key. * * The $key is hashed with a component-specific incrementor, which is used to * invalidate multiple caches at once. * @since 2.7.0 * * @param string $key Unique key for the query. Usually a SQL string. * @param string $group Cache group. Eg 'bp_activity'. * @return string */ function bp_core_get_incremented_cache_key( $key, $group ) { $incrementor = bp_core_get_incrementor( $group ); $cache_key = md5( $key . $incrementor ); return $cache_key; } /** * Gets a group-specific cache incrementor. * * The incrementor is paired with query identifiers (like SQL strings) to * create cache keys that can be invalidated en masse. * * If an incrementor does not yet exist for the given `$group`, one will * be created. * * @since 2.7.0 * * @param string $group Cache group. Eg 'bp_activity'. * @return string */ function bp_core_get_incrementor( $group ) { $incrementor = wp_cache_get( 'incrementor', $group ); if ( ! $incrementor ) { $incrementor = microtime(); wp_cache_set( 'incrementor', $incrementor, $group ); } return $incrementor; } /** * Reset a group-specific cache incrementor. * * Call this function when all incrementor-based caches associated with a given * cache group should be invalidated. * * @since 2.7.0 * * @param string $group Cache group. Eg 'bp_activity'. * @return bool True on success, false on failure. */ function bp_core_reset_incrementor( $group ) { return wp_cache_delete( 'incrementor', $group ); } /** * Resets all incremented bp_invitations caches. * * @since 5.0.0 */ function bp_invitations_reset_cache_incrementor() { bp_core_reset_incrementor( 'bp_invitations' ); } add_action( 'bp_invitation_after_save', 'bp_invitations_reset_cache_incrementor' ); add_action( 'bp_invitation_after_delete', 'bp_invitations_reset_cache_incrementor' ); /** * Add a cache group for Database object types. * * @since 7.0.0 */ function bp_set_object_type_terms_cache_group() { wp_cache_add_global_groups( 'bp_object_terms' ); } add_action( 'bp_setup_cache_groups', 'bp_set_object_type_terms_cache_group' ); /** * Clear the Database object types cache. * * @since 7.0.0 * * @param int $type_id The Type's term ID. * @param string $taxonomy The Type's taxonomy name. */ function bp_clear_object_type_terms_cache( $type_id = 0, $taxonomy = '' ) { wp_cache_delete( $taxonomy, 'bp_object_terms' ); } add_action( 'bp_type_inserted', 'bp_clear_object_type_terms_cache' ); add_action( 'bp_type_updated', 'bp_clear_object_type_terms_cache' ); add_action( 'bp_type_deleted', 'bp_clear_object_type_terms_cache' ); /** * Resets all incremented bp_optout caches. * * @since 8.0.0 */ function bp_optouts_reset_cache_incrementor() { bp_core_reset_incrementor( 'bp_optouts' ); } add_action( 'bp_optout_after_save', 'bp_optouts_reset_cache_incrementor' ); add_action( 'bp_optout_after_delete', 'bp_optouts_reset_cache_incrementor' );