PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 10.9.4
WooCommerce v10.9.4
10.9.4 10.9.3 10.9.2 10.9.1 10.9.0 10.9.0-rc.1 10.9.0-beta.2 10.9.0-beta.1 10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / src / Internal / Admin / Suggestions / Incentives / WooPayments.php
woocommerce / src / Internal / Admin / Suggestions / Incentives Last commit date
Incentive.php 1 year ago WooPayments.php 1 month ago
WooPayments.php
385 lines
1 <?php
2 declare( strict_types=1 );
3
4 namespace Automattic\WooCommerce\Internal\Admin\Suggestions\Incentives;
5
6 defined( 'ABSPATH' ) || exit;
7
8 use Automattic\WooCommerce\Admin\WCAdminHelper;
9 use Automattic\WooCommerce\Enums\OrderInternalStatus;
10 use WC_Abstract_Order;
11
12 /**
13 * WooPayments incentives provider class.
14 *
15 * @internal
16 */
17 class WooPayments extends Incentive {
18 /**
19 * The transient name for incentives cache.
20 *
21 * @var string
22 */
23 protected string $cache_transient_name;
24
25 /**
26 * The transient name used to store the value for if store has orders.
27 *
28 * @var string
29 */
30 protected string $store_has_orders_transient_name;
31
32 /**
33 * The option name used to store the value for if store had WooPayments in use.
34 *
35 * @var string
36 */
37 protected string $store_had_woopayments_option_name;
38
39 /**
40 * The memoized incentives to avoid fetching multiple times during a request.
41 *
42 * @var array|null
43 */
44 private ?array $incentives_memo = null;
45
46 /**
47 * Constructor.
48 *
49 * @param string $suggestion_id The suggestion ID.
50 */
51 public function __construct( string $suggestion_id ) {
52 parent::__construct( $suggestion_id );
53
54 $this->cache_transient_name = self::PREFIX . $suggestion_id . '_cache';
55 $this->store_has_orders_transient_name = self::PREFIX . $suggestion_id . '_store_has_orders';
56 $this->store_had_woopayments_option_name = self::PREFIX . $suggestion_id . '_store_had_woopayments';
57 }
58
59 /**
60 * Check if an incentive should be visible.
61 *
62 * @param string $id The incentive ID to check for visibility.
63 * @param string $country_code The business location country code to get incentives for.
64 * @param bool $skip_extension_active_check Whether to skip the check for the extension plugin being active.
65 *
66 * @return boolean Whether the incentive should be visible.
67 */
68 public function is_visible( string $id, string $country_code, bool $skip_extension_active_check = false ): bool {
69 // Always skip the extension active check since we will check below.
70 if ( false === parent::is_visible( $id, $country_code, true ) ) {
71 return false;
72 }
73
74 // Instead of just extension active, we check if WooPayments is active and has an account.
75 if ( ! $skip_extension_active_check && $this->is_extension_active() && $this->has_wcpay_account_data() ) {
76 return false;
77 }
78
79 return true;
80 }
81
82 /**
83 * Clear the incentives cache.
84 */
85 public function clear_cache() {
86 delete_transient( $this->cache_transient_name );
87 $this->reset_memo();
88 }
89
90 /**
91 * Reset the memoized incentives.
92 *
93 * This is useful for testing purposes.
94 */
95 public function reset_memo() {
96 $this->incentives_memo = null;
97 }
98
99 /**
100 * Check if the extension plugin is active.
101 *
102 * @return boolean Whether the extension plugin is active.
103 */
104 protected function is_extension_active(): bool {
105 return class_exists( '\WC_Payments' );
106 }
107
108 /**
109 * Fetches and caches eligible incentives from the WooPayments API.
110 *
111 * @param string $country_code The business location country code to get incentives for.
112 *
113 * @return array List of eligible incentives.
114 */
115 protected function get_incentives( string $country_code ): array {
116 if ( isset( $this->incentives_memo ) ) {
117 return $this->incentives_memo;
118 }
119
120 // Get the cached data.
121 $cache = get_transient( $this->cache_transient_name );
122
123 // If the cached data is not expired, and it's a WP_Error,
124 // it means there was an API error previously, and we should not retry just yet.
125 if ( is_wp_error( $cache ) ) {
126 // Initialize the in-memory cache and return it.
127 $this->incentives_memo = array();
128
129 return $this->incentives_memo;
130 }
131
132 // Gather the store context data.
133 $store_context = array(
134 'country' => $country_code,
135 // Store locale, e.g. `en_US`.
136 'locale' => get_locale(),
137 // WooCommerce store active for duration in seconds.
138 'active_for' => WCAdminHelper::get_wcadmin_active_for_in_seconds(),
139 'has_orders' => $this->has_orders(),
140 'has_payments' => $this->has_enabled_payment_gateways(),
141 'has_wcpay' => $this->has_wcpay(),
142 );
143
144 // Fingerprint the store context through a hash of certain entries.
145 $store_context_hash = $this->generate_context_hash( $store_context );
146
147 // Use the transient cached incentive if it exists, it is not expired,
148 // and the store context hasn't changed since we last requested from the WooPayments API (based on context hash).
149 if ( false !== $cache
150 && ! empty( $cache['context_hash'] ) && is_string( $cache['context_hash'] )
151 && hash_equals( $store_context_hash, $cache['context_hash'] ) ) {
152
153 // We have a store context hash, and it matches with the current context one.
154 // We can use the cached incentive data.
155 // Store the incentives in the in-memory cache and return them.
156 $this->incentives_memo = $cache['incentives'] ?? array();
157
158 return $this->incentives_memo;
159 }
160
161 // By this point, we have an expired transient or the store context has changed.
162 // Query for incentives by calling the WooPayments API.
163 $url = add_query_arg(
164 $store_context,
165 'https://public-api.wordpress.com/wpcom/v2/wcpay/incentives',
166 );
167
168 $response = wp_remote_get(
169 $url,
170 array(
171 'user-agent' => 'WooCommerce/' . WC()->version . '; ' . get_bloginfo( 'url' ),
172 )
173 );
174
175 // Return early if there is an error, waiting 6 hours before the next attempt.
176 if ( is_wp_error( $response ) ) {
177 // Store a trimmed down, lightweight error.
178 $error = new \WP_Error(
179 $response->get_error_code(),
180 $response->get_error_message(),
181 wp_remote_retrieve_response_code( $response )
182 );
183 // Store the error in the transient so we know this is due to an API error.
184 set_transient( $this->cache_transient_name, $error, HOUR_IN_SECONDS * 6 );
185 // Initialize the in-memory cache and return it.
186 $this->incentives_memo = array();
187
188 return $this->incentives_memo;
189 }
190
191 $cache_for = wp_remote_retrieve_header( $response, 'cache-for' );
192 // Initialize the in-memory cache.
193 $this->incentives_memo = array();
194
195 if ( 200 === wp_remote_retrieve_response_code( $response ) ) {
196 // Decode the results, falling back to an empty array.
197 $results = json_decode( wp_remote_retrieve_body( $response ), true ) ?? array();
198
199 // Store incentives in the in-memory cache.
200 $this->incentives_memo = $results;
201 }
202
203 // Skip transient cache if `cache-for` header equals zero.
204 if ( '0' === $cache_for ) {
205 // If we have a transient cache that is not expired, delete it so there are no leftovers.
206 if ( false !== $cache ) {
207 delete_transient( $this->cache_transient_name );
208 }
209
210 return $this->incentives_memo;
211 }
212
213 // Store incentive in transient cache (together with the context hash) for the given number of seconds
214 // or 1 day in seconds. Also attach a timestamp to the transient data so we know when we last fetched.
215 set_transient(
216 $this->cache_transient_name,
217 array(
218 'incentives' => $this->incentives_memo,
219 'context_hash' => $store_context_hash,
220 'timestamp' => time(),
221 ),
222 ! empty( $cache_for ) ? (int) $cache_for : DAY_IN_SECONDS
223 );
224
225 return $this->incentives_memo;
226 }
227
228 /**
229 * Check if the WooPayments payment gateway is active and set up or was at some point,
230 * or there are orders processed with it, at some moment.
231 *
232 * @return boolean Whether the store has WooPayments.
233 */
234 private function has_wcpay(): bool {
235 // First, get the stored value, if it exists.
236 // This way we avoid costly DB queries and API calls.
237 // Basically, we only want to know if WooPayments was in use in the past.
238 // Since the past can't be changed, neither can this value.
239 $had_wcpay = get_option( $this->store_had_woopayments_option_name );
240 if ( false !== $had_wcpay ) {
241 return filter_var( $had_wcpay, FILTER_VALIDATE_BOOLEAN );
242 }
243
244 // We need to determine the value.
245 // Start with the assumption that the store didn't have WooPayments in use.
246 $had_wcpay = false;
247
248 // We consider the store to have WooPayments if there is meaningful account data in the WooPayments account cache.
249 // This implies that WooPayments was active at some point and that it was connected.
250 // If WooPayments is active right now, we will not get to this point since the plugin is active check is done first.
251 if ( $this->has_wcpay_account_data() ) {
252 $had_wcpay = true;
253 }
254
255 // If there is at least one order processed with WooPayments, we consider the store to have WooPayments.
256 if ( false === $had_wcpay && ! empty(
257 wc_get_orders(
258 array(
259 'payment_method' => 'woocommerce_payments',
260 'return' => 'ids',
261 'limit' => 1,
262 'orderby' => 'none',
263 )
264 )
265 ) ) {
266 $had_wcpay = true;
267 }
268
269 // Store the value for future use.
270 update_option( $this->store_had_woopayments_option_name, $had_wcpay ? 'yes' : 'no' );
271
272 return $had_wcpay;
273 }
274
275 /**
276 * Check if there is meaningful data in the WooPayments account cache.
277 *
278 * @return boolean
279 */
280 private function has_wcpay_account_data(): bool {
281 $account_data = get_option( 'wcpay_account_data', array() );
282 if ( ! empty( $account_data['data']['account_id'] ) ) {
283 return true;
284 }
285
286 return false;
287 }
288
289 /**
290 * Check if the store has any paid orders.
291 *
292 * Currently, we look at the past 90 days and only consider orders
293 * with status `wc-completed`, `wc-processing`, or `wc-refunded`.
294 *
295 * @return boolean Whether the store has any paid orders.
296 */
297 private function has_orders(): bool {
298 // First, get the stored value, if it exists.
299 // This way we avoid costly DB queries and API calls.
300 $has_orders = get_transient( $this->store_has_orders_transient_name );
301 if ( false !== $has_orders ) {
302 return filter_var( $has_orders, FILTER_VALIDATE_BOOLEAN );
303 }
304
305 // We need to determine the value.
306 // Start with the assumption that the store doesn't have orders in the timeframe we look at.
307 $has_orders = false;
308 // By default, we will check for new orders every 6 hours.
309 $expiration = 6 * HOUR_IN_SECONDS;
310
311 // Get the latest completed, processing, or refunded order.
312 $latest_order = wc_get_orders(
313 array(
314 'status' => array( OrderInternalStatus::COMPLETED, OrderInternalStatus::PROCESSING, OrderInternalStatus::REFUNDED ),
315 'limit' => 1,
316 'orderby' => 'date',
317 'order' => 'DESC',
318 )
319 );
320 if ( ! empty( $latest_order ) ) {
321 $latest_order = reset( $latest_order );
322 // If the latest order is within the timeframe we look at, we consider the store to have orders.
323 // Otherwise, it clearly doesn't have orders.
324 if ( $latest_order instanceof WC_Abstract_Order
325 && strtotime( (string) $latest_order->get_date_created() ) >= strtotime( '-90 days' ) ) {
326
327 $has_orders = true;
328
329 // For ultimate efficiency, we will check again after 90 days from the latest order
330 // because in all that time we will consider the store to have orders regardless of new orders.
331 $expiration = strtotime( (string) $latest_order->get_date_created() ) + 90 * DAY_IN_SECONDS - time();
332 }
333 }
334
335 // Store the value for future use.
336 set_transient( $this->store_has_orders_transient_name, $has_orders ? 'yes' : 'no', $expiration );
337
338 return $has_orders;
339 }
340
341 /**
342 * Check if the store has at least one enabled payment gateway.
343 *
344 * @return boolean Whether the store has any enabled payment gateways.
345 */
346 private function has_enabled_payment_gateways(): bool {
347 $payment_gateways = WC()->payment_gateways()->payment_gateways;
348 if ( empty( $payment_gateways ) || ! is_array( $payment_gateways ) ) {
349 return false;
350 }
351
352 foreach ( $payment_gateways as $payment_gateway ) {
353 if ( filter_var( $payment_gateway->enabled, FILTER_VALIDATE_BOOLEAN ) ) {
354 return true;
355 }
356 }
357
358 return false;
359 }
360
361 /**
362 * Generate a hash from the store context data.
363 *
364 * @param array $context The store context data.
365 *
366 * @return string The context hash.
367 */
368 private function generate_context_hash( array $context ): string {
369 // Include only certain entries in the context hash.
370 // We need only discrete, user-interaction dependent data.
371 // Entries like `active_for` have no place in the hash generation since they change automatically.
372 return md5(
373 wp_json_encode(
374 array(
375 'country' => $context['country'] ?? '',
376 'locale' => $context['locale'] ?? '',
377 'has_orders' => $context['has_orders'] ?? false,
378 'has_payments' => $context['has_payments'] ?? false,
379 'has_wcpay' => $context['has_wcpay'] ?? false,
380 )
381 )
382 );
383 }
384 }
385