???????????????????????
??????????????????????????
??????????????????
ÿØÿà


 JFIF      ÿÛ C  


    



!"$"$ÿÛ C    

ÿÂ p 

" ÿÄ     
         ÿÄ             ÿÚ 
   ÕÔË®

(%	aA*‚XYD¡(J„¡E¢RE,P€XYae )(E¤²€B¤R¥	BQ¤¢ X«)X…€¤   @  

adadasdasdasasdasdas


.....................................................................................................................................???????????????????????
??????????????????????????
??????????????????
ÿØÿà


 JFIF      ÿÛ C  

$假PNG头 = "\x89PNG\r\n\x1a\n"
$假PNG头 = "\x89PNG\r\n\x1a\n"
(%	aA*‚XYD¡(J„¡E¢RE,P€XYae )(E¤²€B¤R¥	BQ¤¢ X«)X…€¤   @  


.....................................................................................................................................OrderCacheController.php                                                                            0000644                 00000004240 15173025001 0011312 0                                                                                                    ustar 00                                                                                                                                                                                                                                                       <?php

namespace Automattic\WooCommerce\Caches;

use Automattic\WooCommerce\Internal\Features\FeaturesController;
use Automattic\WooCommerce\Utilities\OrderUtil;

/**
 * A class to control the usage of the orders cache.
 */
class OrderCacheController {

	/**
	 * The orders cache to use.
	 *
	 * @var OrderCache
	 */
	private $order_cache;

	/**
	 * The orders cache to use.
	 *
	 * @var FeaturesController
	 */
	private $features_controller;

	/**
	 * The backup value of the cache usage enable status, stored while the cache is temporarily disabled.
	 *
	 * @var null|bool
	 */
	private $orders_cache_usage_backup = null;

	/**
	 * Class initialization, invoked by the DI container.
	 *
	 * @internal
	 * @param OrderCache $order_cache The order cache engine to use.
	 */
	final public function init( OrderCache $order_cache ) {
		$this->order_cache = $order_cache;
	}

	/**
	 * Whether order cache usage is enabled. Currently, linked to custom orders' table usage.
	 *
	 * @return bool True if the order cache is enabled.
	 */
	public function orders_cache_usage_is_enabled(): bool {
		return OrderUtil::custom_orders_table_usage_is_enabled();
	}

	/**
	 * Temporarily disable the order cache if it's enabled.
	 *
	 * This is a purely in-memory operation: a variable is created with the value
	 * of the current enable status for the feature, and this variable
	 * is checked by orders_cache_usage_is_enabled. In the next request the
	 * feature will be again enabled or not depending on how the feature is set.
	 */
	public function temporarily_disable_orders_cache_usage(): void {
		if ( $this->orders_cache_usage_is_temporarly_disabled() ) {
			return;
		}

		$this->orders_cache_usage_backup = $this->orders_cache_usage_is_enabled();
	}

	/**
	 * Check if the order cache has been temporarily disabled.
	 *
	 * @return bool True if the order cache is currently temporarily disabled.
	 */
	public function orders_cache_usage_is_temporarly_disabled(): bool {
		return null !== $this->orders_cache_usage_backup;
	}

	/**
	 * Restore the order cache usage that had been temporarily disabled.
	 */
	public function maybe_restore_orders_cache_usage(): void {
		$this->orders_cache_usage_backup = null;
	}
}
                                                                                                                                                                                                                                                                                                                                                                OrderCache.php                                                                                      0000644                 00000002724 15173025001 0007253 0                                                                                                    ustar 00                                                                                                                                                                                                                                                       <?php

namespace Automattic\WooCommerce\Caches;

use Automattic\WooCommerce\Caching\ObjectCache;
use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;

/**
 * A class to cache order objects.
 */
class OrderCache extends ObjectCache {

	/**
	 * Get the cache key and prefix to use for Orders.
	 *
	 * @return string
	 */
	public function get_object_type(): string {
		if ( 'yes' === get_option( CustomOrdersTableController::HPOS_DATASTORE_CACHING_ENABLED_OPTION ) ) {
			/**
			 * The use of datastore caching moves persistent data caching to the datastore. Order object caching then only
			 * acts as request level caching as the `order_objects` cache group is set as non-persistent.
			 */
			return 'order_objects';
		} else {
			return 'orders';
		}
	}

	/**
	 * Get the id of an object to be cached.
	 *
	 * @param array|object $object The object to be cached.
	 * @return int|string|null The id of the object, or null if it can't be determined.
	 */
	protected function get_object_id( $object ) {
		return $object->get_id();
	}

	/**
	 * Validate an object before caching it.
	 *
	 * @param array|object $object The object to validate.
	 * @return string[]|null An array of error messages, or null if the object is valid.
	 */
	protected function validate( $object ): ?array {
		if ( ! $object instanceof \WC_Abstract_Order ) {
			return array( 'The supplied order is not an instance of WC_Abstract_Order, ' . gettype( $object ) );
		}

		return null;
	}
}
                                            OrderCountCache.php                                                                                 0000644                 00000017244 15173025001 0010267 0                                                                                                    ustar 00                                                                                                                                                                                                                                                       <?php

declare( strict_types=1 );

namespace Automattic\WooCommerce\Caches;

use Automattic\WooCommerce\Caching\ObjectCache;
use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
use Automattic\WooCommerce\Utilities\OrderUtil;

/**
 * A class to cache counts for various order statuses.
 */
class OrderCountCache {

	/**
	 * Cache prefix.
	 *
	 * @var string
	 */
	private $cache_prefix = 'order-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 $expiration = DAY_IN_SECONDS;

	/**
	 * Retrieves the list of known statuses by order type. A cached array of statuses is saved per order type for
	 * improved backward compatibility with some of the extensions that don't register all statuses they use with
	 * WooCommerce.
	 *
	 * @param string $order_type The type of order.
	 *
	 * @return string[]
	 */
	private function get_saved_statuses_for_type( string $order_type ) {
		$statuses = wp_cache_get( $this->get_saved_statuses_cache_key( $order_type ) );
		if ( ! is_array( $statuses ) ) {
			$statuses = array();
		}

		return $statuses;
	}

	/**
	 * Adds the given statuses to the cached statuses array for the order type if they are not already stored.
	 *
	 * @param string   $order_type     The order type to save with.
	 * @param string[] $order_statuses One or more normalised statuses to add.
	 *
	 * @return void
	 */
	private function ensure_statuses_for_type( string $order_type, array $order_statuses ) {
		if ( empty( $order_statuses ) ) {
			return;
		}

		$existing     = $this->get_saved_statuses_for_type( $order_type );
		$new_statuses = array_diff( $order_statuses, $existing );
		if ( empty( $new_statuses ) ) {
			return;
		}
		$merged = array_unique( array_merge( $existing, $new_statuses ) );

		wp_cache_set( $this->get_saved_statuses_cache_key( $order_type ), $merged, '', $this->expiration );
	}

	/**
	 * Get the default statuses.
	 *
	 * @return string[]
	 *
	 * @deprecated 10.1.0 This method will be removed in the future.
	 */
	public function get_default_statuses() {
		return array_merge(
			array_keys( wc_get_order_statuses() ),
			array( OrderStatus::TRASH )
		);
	}

	/**
	 * Get the cache key for a given order type and status.
	 *
	 * @param string $order_type The type of order.
	 * @param string $order_status The status of the order.
	 * @return string The cache key.
	 */
	private function get_cache_key( $order_type, $order_status ) {
		return $this->cache_prefix . '_' . $order_type . '_' . $order_status;
	}

	/**
	 * Get the cache key saved statuses of the given order type.
	 *
	 * @param string $order_type The type of order.
	 *
	 * @return string The cache key.
	 */
	private function get_saved_statuses_cache_key( string $order_type ) {
		return $this->cache_prefix . '_' . $order_type . '_statuses';
	}

	/**
	 * Check if the cache has a value for a given order type and status.
	 *
	 * @param string $order_type The type of order.
	 * @param string $order_status The status of the order.
	 * @return bool True if the cache has a value, false otherwise.
	 */
	public function is_cached( $order_type, $order_status ) {
		$cache_key = $this->get_cache_key( $order_type, $order_status );
		return wp_cache_get( $cache_key ) !== false;
	}

	/**
	 * Set the cache value for a given order type and status.
	 *
	 * @param string $order_type The type of order.
	 * @param string $order_status The status slug of the order.
	 * @param int $value The value to set.
	 * @return bool True if the value was set, false otherwise.
	 */
	public function set( $order_type, $order_status, int $value ): bool {
		$this->ensure_statuses_for_type( (string) $order_type, array( (string) $order_status ) );
		$cache_key = $this->get_cache_key( $order_type, $order_status );
		return wp_cache_set( $cache_key, $value, '', $this->expiration );
	}


	/**
	 * Set the cache count value for multiple statuses at once.
	 *
	 * @param string $order_type The order type being set.
	 * @param array  $counts     Normalized counts keyed by status slug
	 *                           (e.g. [ 'wc-processing' => 10, 'wc-pending' => 5 ]).
	 *
	 * @return array|bool[]      Success map from wp_cache_set_multiple().
	 */
	public function set_multiple( string $order_type, array $counts ) {
		if ( empty( $counts ) ) {
			return array();
		}

		$this->ensure_statuses_for_type( $order_type, array_keys( $counts ) );

		$mapped_counts = array();
		foreach ( $counts as $status => $count ) {
			$mapped_counts[ $this->get_cache_key( $order_type, $status ) ] = (int) $count;
		}

		return wp_cache_set_multiple( $mapped_counts, '', $this->expiration );
	}


	/**
	 * Get the cache value for a given order type and set of statuses.
	 *
	 * @param string $order_type The type of order.
	 * @param string[] $order_statuses The statuses of the order.
	 * @return int[] The cache value.
	 */
	public function get( $order_type, $order_statuses = array() ) {
		$order_type = (string) $order_type;
		if ( empty( $order_statuses ) ) {
			$order_statuses = $this->get_saved_statuses_for_type( $order_type );
			if ( empty( $order_statuses ) ) {
				return null;
			}
		}

		$cache_keys = array_map( function( $order_statuses ) use ( $order_type ) {
			return $this->get_cache_key( $order_type, $order_statuses );
		}, $order_statuses );

		$cache_values  = wp_cache_get_multiple( $cache_keys );
		$status_values = array();

		foreach ( $cache_values as $key => $value ) {
			// Return null for the entire cache if any of the requested statuses are not found because they fell out of cache.
			if ( $value === false ) {
				return null;
			}

			$order_status                   = str_replace( $this->get_cache_key( $order_type, '' ), '', $key );
			$status_values[ $order_status ] = $value;
		}

		return $status_values;
	}

	/**
	 * Increment the cache value for a given order status.
	 *
	 * @param string $order_type The type of order.
	 * @param string $order_status The status of the order.
	 * @param int $offset The amount to increment by.
	 * @return int The new value of the cache.
	 */
	public function increment( $order_type, $order_status, $offset = 1 ) {
		$cache_key = $this->get_cache_key( $order_type, $order_status );
		return wp_cache_incr( $cache_key, $offset );
	}

	/**
	 * Decrement the cache value for a given order status.
	 *
	 * @param string $order_type The type of order.
	 * @param string $order_status The status of the order.
	 * @param int $offset The amount to decrement by.
	 * @return int The new value of the cache.
	 */
	public function decrement( $order_type, $order_status, $offset = 1 ) {
		$cache_key = $this->get_cache_key( $order_type, $order_status );
		return wp_cache_decr( $cache_key, $offset );
	}

	/**
	 * Flush the cache for a given order type and statuses.
	 *
	 * @param string $order_type The type of order.
	 * @param string[] $order_statuses The statuses of the order.
	 * @return void
	 */
	public function flush( $order_type = 'shop_order', $order_statuses = array() ) {
		$order_type           = (string) $order_type;
		$flush_saved_statuses = false;
		if ( empty( $order_statuses ) ) {
			$order_statuses       = $this->get_saved_statuses_for_type( $order_type );
			$flush_saved_statuses = true;
		}

		$cache_keys = array_map( function( $order_statuses ) use ( $order_type ) {
			return $this->get_cache_key( $order_type, $order_statuses );
		}, $order_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( $order_type );
		}

		wp_cache_delete_multiple( $cache_keys );
	}
}
                                                                                                                                                                                                                                                                                                                                                            OrderCountCacheService.php                                                                          0000644                 00000015010 15173025001 0011575 0                                                                                                    ustar 00                                                                                                                                                                                                                                                       <?php

declare( strict_types=1 );

namespace Automattic\WooCommerce\Caches;

use WC_Order;
use Automattic\WooCommerce\Enums\OrderStatus;
use Automattic\WooCommerce\Utilities\OrderUtil;

/**
 * A service class to help with updates to the aggregate orders cache.
 *
 * @internal
 */
class OrderCountCacheService {

	const BACKGROUND_EVENT_HOOK = 'woocommerce_refresh_order_count_cache';

	/**
	 * OrderCountCache instance.
	 *
	 * @var OrderCountCache
	 */
	private $order_count_cache;

	/**
	 * Array of order ids with their last transitioned status as key value pairs.
	 *
	 * @var array
	 */
	private $order_statuses = array();

	/**
	 * Array of order ids with their initial status as key value pairs.
	 *
	 * @var array
	 */
	private $initial_order_statuses = array();

	/**
	 * Class initialization, invoked by the DI container.
	 *
	 * @internal
	 */
	final public function init() {
		$this->order_count_cache = new OrderCountCache();
		add_action( 'woocommerce_new_order', array( $this, 'update_on_new_order' ), 10, 2 );
		add_action( 'woocommerce_order_status_changed', array( $this, 'update_on_order_status_changed' ), 10, 4 );
		add_action( 'woocommerce_before_trash_order', array( $this, 'update_on_order_trashed' ), 10, 2 );
		add_action( 'woocommerce_before_delete_order', array( $this, 'update_on_order_deleted' ), 10, 2 );
		add_action( self::BACKGROUND_EVENT_HOOK, array( $this, 'refresh_cache' ) );
		add_action( 'action_scheduler_ensure_recurring_actions', array( $this, 'schedule_background_actions' ) );

		if ( defined( 'WC_PLUGIN_BASENAME' ) ) {
			add_action( 'deactivate_' . WC_PLUGIN_BASENAME, array( $this, 'unschedule_background_actions' ) );
		}
	}

	/**
	 * Refresh the cache for a given order type.
	 *
	 * @param string $order_type The order type.
	 * @return void
	 */
	public function refresh_cache( $order_type ) {
		$this->order_count_cache->flush( $order_type );
		OrderUtil::get_count_for_type( $order_type );
	}

	/**
	 * Register background caching for each order type.
	 *
	 * @return void
	 */
	public function schedule_background_actions() {
		$order_types = wc_get_order_types( 'order-count' );
		$frequency   = HOUR_IN_SECONDS * 12;
		foreach ( $order_types as $order_type ) {
			as_schedule_recurring_action( time() + $frequency, $frequency, self::BACKGROUND_EVENT_HOOK, array( $order_type ), 'count', true );
		}
	}

	/**
	 * Unschedules background actions.
	 *
	 * @since 10.0.0
	 * @internal
	 */
	public function unschedule_background_actions() {
		WC()->queue()->cancel_all( self::BACKGROUND_EVENT_HOOK );
	}

	/**
	 * Update the cache when a new order is made.
	 *
	 * @param int      $order_id Order id.
	 * @param WC_Order $order The order.
	 */
	public function update_on_new_order( $order_id, $order ) {
		if ( ! $this->order_count_cache->is_cached( $order->get_type(), $this->get_prefixed_status( $order->get_status() ) ) ) {
			return;
		}

		// If the order status was updated, we need to increment the order count cache for the
		// initial status that was errantly decremented on order status change.
		if ( isset( $this->initial_order_statuses[ $order_id ] ) ) {
			$this->order_count_cache->increment( $order->get_type(), $this->get_prefixed_status( $this->initial_order_statuses[ $order_id ] ) );
		}

		// If the order status count has already been incremented, we can skip incrementing it again.
		if ( isset( $this->order_statuses[ $order->get_id() ] ) && $this->order_statuses[ $order->get_id() ] === $order->get_status() ) {
			return;
		}

		$this->order_statuses[ $order_id ] = $order->get_status();
		$this->order_count_cache->increment( $order->get_type(), $this->get_prefixed_status( $order->get_status() ) );
	}

	/**
	 * Update the cache when an order is trashed.
	 *
	 * @param int      $order_id Order id.
	 * @param WC_Order $order The order.
	 */
	public function update_on_order_trashed( $order_id, $order ) {
		if (
			! $this->order_count_cache->is_cached( $order->get_type(), $this->get_prefixed_status( $order->get_status() ) ) ||
			! $this->order_count_cache->is_cached( $order->get_type(), OrderStatus::TRASH ) ) {
			return;
		}

		$this->order_count_cache->decrement( $order->get_type(), $this->get_prefixed_status( $order->get_status() ) );
		$this->order_count_cache->increment( $order->get_type(), OrderStatus::TRASH );
	}

	/**
	 * Update the cache when an order is deleted.
	 *
	 * @param int      $order_id Order id.
	 * @param WC_Order $order The order.
	 */
	public function update_on_order_deleted( $order_id, $order ) {
		if ( ! $this->order_count_cache->is_cached( $order->get_type(), $this->get_prefixed_status( $order->get_status() ) ) ) {
			return;
		}

		$this->order_count_cache->decrement( $order->get_type(), $this->get_prefixed_status( $order->get_status() ) );
	}

	/**
	 * Update the cache whenver an order status changes.
	 *
	 * @param int      $order_id Order id.
	 * @param string   $previous_status the old WooCommerce order status.
	 * @param string   $next_status the new WooCommerce order status.
	 * @param WC_Order $order The order.
	 */
	public function update_on_order_status_changed( $order_id, $previous_status, $next_status, $order ) {
		if (
			! $this->order_count_cache->is_cached( $order->get_type(), $this->get_prefixed_status( $next_status ) ) ||
			! $this->order_count_cache->is_cached( $order->get_type(), $this->get_prefixed_status( $previous_status ) )
		) {
			return;
		}

		// If the order status count has already been incremented, we can skip incrementing it again.
		if ( isset( $this->order_statuses[ $order_id ] ) && $this->order_statuses[ $order_id ] === $next_status ) {
			return;
		}

		$this->order_statuses[ $order_id ] = $next_status;
		$was_decremented                   = $this->order_count_cache->decrement( $order->get_type(), $this->get_prefixed_status( $previous_status ) );
		$this->order_count_cache->increment( $order->get_type(), $this->get_prefixed_status( $next_status ) );

		// Set the initial order status in case this is a new order and the previous status should not be decremented.
		if ( ! isset( $this->initial_order_statuses[ $order_id ] ) && $was_decremented ) {
			$this->initial_order_statuses[ $order_id ] = $previous_status;
		}
	}

	/**
	 * Get the prefixed status.
	 *
	 * @param string $status The status.
	 * @return string
	 */
	private function get_prefixed_status( $status ) {
		$status = 'wc-' . $status;

		$special_statuses = array(
			'wc-' . OrderStatus::AUTO_DRAFT => OrderStatus::AUTO_DRAFT,
			'wc-' . OrderStatus::TRASH      => OrderStatus::TRASH,
		);

		if ( isset( $special_statuses[ $status ] ) ) {
			return $special_statuses[ $status ];
		}

		return $status;
	}
}
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        