Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
betrayful
/
wp
/
wp-content
/
plugins
/
woocommerce
/
src
/
Caches
:
ProductCountCache.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?php declare( strict_types=1 ); namespace Automattic\WooCommerce\Caches; /** * A class to cache counts for various product statuses. */ class ProductCountCache { /** * Cache prefix. * * @var string */ private string $cache_prefix = 'product-count'; /** * Default value for the duration of the objects in the cache, in seconds * (may not be used depending on the cache engine used WordPress cache implementation). * * @var int */ protected int $expiration = DAY_IN_SECONDS; /** * Retrieves the list of known statuses by product type. A cached array of statuses is saved per product type for * improved backward compatibility with some of the extensions that don't register all statuses they use with * WooCommerce. * * @param string $product_type The post type (e.g. 'product', 'product_variation'). * * @return string[] */ private function get_saved_statuses_for_type( string $product_type ): array { $cache_key = $this->get_saved_statuses_cache_key( $product_type ); $statuses = wp_cache_get( $cache_key ); // Defensive perimeter: purge corrupted cache entries (external cache modification). if ( false !== $statuses && ( ! is_array( $statuses ) || array_filter( $statuses, 'is_string' ) !== $statuses ) ) { $statuses = false; wp_cache_delete( $cache_key ); } return is_array( $statuses ) ? $statuses : array(); } /** * Adds the given statuses to the cached statuses array for the product type if they are not already stored. * * @param string $product_type The post type (e.g. 'product', 'product_variation'). * @param string[] $product_statuses One or more statuses to add. * * @return void */ private function ensure_statuses_for_type( string $product_type, array $product_statuses ): void { if ( empty( $product_statuses ) ) { return; } $existing = $this->get_saved_statuses_for_type( $product_type ); $new_statuses = array_diff( $product_statuses, $existing ); if ( empty( $new_statuses ) ) { return; } $merged = array_unique( array_merge( $existing, $new_statuses ) ); wp_cache_set( $this->get_saved_statuses_cache_key( $product_type ), $merged, '', $this->expiration ); } /** * Get the cache key for a given product type and status. * * @param string $product_type The post type (e.g. 'product', 'product_variation'). * @param string $product_status The status of the product. * * @return string */ private function get_cache_key( string $product_type, string $product_status ): string { return $this->cache_prefix . '_' . $product_type . '_' . $product_status; } /** * Get the cache key for saved statuses of the given product type. * * @param string $product_type The post type (e.g. 'product', 'product_variation'). * * @return string */ private function get_saved_statuses_cache_key( string $product_type ): string { return $this->cache_prefix . '_' . $product_type . '_statuses'; } /** * Check if the cache has a value for a given product type and status. * * @param string $product_type The post type (e.g. 'product', 'product_variation'). * @param string $product_status The status of the product. * * @return bool */ public function is_cached( string $product_type, string $product_status ): bool { return false !== wp_cache_get( $this->get_cache_key( $product_type, $product_status ) ); } /** * Set the cache value for a given product type and status. * * @param string $product_type The post type (e.g. 'product', 'product_variation'). * @param string $product_status The status slug of the product. * @param int $value The value to set. * * @return bool */ public function set( string $product_type, string $product_status, int $value ): bool { $this->ensure_statuses_for_type( $product_type, array( $product_status ) ); return wp_cache_set( $this->get_cache_key( $product_type, $product_status ), $value, '', $this->expiration ); } /** * Set the cache count value for multiple statuses at once. * * @deprecated 11.1.0 * * @param string $product_type The post type (e.g. 'product', 'product_variation'). * @param array<string,int> $counts Counts keyed by status slug (e.g. [ 'publish' => 10, 'draft' => 5 ]). * * @return array<string,bool> */ public function set_multiple( string $product_type, array $counts ) { $results = array(); foreach ( $counts as $status => $count ) { $results[ $this->get_cache_key( $product_type, (string) $status ) ] = $this->set( $product_type, (string) $status, (int) $count ); } return $results; } /** * Get the cache value for a given product type and set of statuses. * * @param string $product_type The post type (e.g. 'product', 'product_variation'). * @param string[] $product_statuses The statuses to retrieve. * * @return array<string,int>|null */ public function get( string $product_type, array $product_statuses = array() ) { if ( empty( $product_statuses ) ) { $product_statuses = $this->get_saved_statuses_for_type( $product_type ); if ( empty( $product_statuses ) ) { return null; } } $cache_keys = array_map( fn( $product_status ) => $this->get_cache_key( $product_type, $product_status ), $product_statuses ); $cache_values = wp_cache_get_multiple( $cache_keys ); $status_values = array(); $cache_key_prefix = $this->get_cache_key( $product_type, '' ); foreach ( $cache_values as $key => $value ) { // Defensive perimeter: purge corrupted cache entries (external cache modification); // As some object caching plugins are pushing integer but pulling string, we use is_numeric here. if ( false !== $value && ! is_numeric( $value ) ) { $value = false; wp_cache_delete( $key ); } // Return null for the entire cache if any of the requested statuses are not found because they fell out of cache. if ( false === $value ) { return null; } $status = substr( $key, strlen( $cache_key_prefix ) ); $status_values[ $status ] = (int) $value; } return $status_values; } /** * Increment the cache value for a given product type and status. * * @param string $product_type The post type (e.g. 'product', 'product_variation'). * @param string $product_status The status of the product. * @param int $offset The amount to increment by. * * @return int|false */ public function increment( string $product_type, string $product_status, int $offset = 1 ) { return wp_cache_incr( $this->get_cache_key( $product_type, $product_status ), $offset ); } /** * Decrement the cache value for a given product type and status. * * @param string $product_type The post type (e.g. 'product', 'product_variation'). * @param string $product_status The status of the product. * @param int $offset The amount to decrement by. * * @return int|false */ public function decrement( string $product_type, string $product_status, int $offset = 1 ) { return wp_cache_decr( $this->get_cache_key( $product_type, $product_status ), $offset ); } /** * Flush the cache for a given product type and statuses. * * @param string $product_type The post type (e.g. 'product', 'product_variation'). * @param string[] $product_statuses The statuses to flush. Flushes all known statuses if empty. * * @return void */ public function flush( string $product_type = 'product', array $product_statuses = array() ): void { $flush_saved_statuses = false; if ( empty( $product_statuses ) ) { $product_statuses = $this->get_saved_statuses_for_type( $product_type ); $flush_saved_statuses = true; } $cache_keys = array_map( fn ( $product_status ) => $this->get_cache_key( $product_type, $product_status ), $product_statuses ); if ( $flush_saved_statuses ) { // If all statuses are being flushed, go ahead and flush the status list so any permanently removed statuses are cleared out. $cache_keys[] = $this->get_saved_statuses_cache_key( $product_type ); } wp_cache_delete_multiple( $cache_keys ); } }