PluginProbe ʕ •ᴥ•ʔ
WooCommerce Square / 5.4.3
WooCommerce Square v5.4.3
5.4.3 5.4.2 5.4.1 5.4.0 trunk 1.0.25 1.0.26 1.0.27 1.0.28 1.0.29 1.0.30 1.0.31 1.0.32 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.38 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.5.3 2.6.0 2.7.0 2.8.0 2.9.0 2.9.1 3.0.0 3.0.1 3.0.2 3.0.3 3.1.0 3.2.0 3.3.0 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.7.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 4.0.0 4.1.0 4.2.0 4.2.1 4.2.2 4.2.3 4.3.0 4.3.1 4.3.2 4.4.0 4.4.1 4.4.2 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.6.2 4.6.3 4.6.4 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.1 4.8.2 4.8.3 4.8.4 4.8.5 4.8.6 4.8.7 4.8.8 4.9.0 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 4.9.6 4.9.7 4.9.8 4.9.9 5.0.0 5.0.1 5.1.0 5.1.1 5.1.2 5.2.0 5.3.0 5.3.1 5.3.2 5.3.3
woocommerce-square / includes / Utilities / Coupon_Utility.php
woocommerce-square / includes / Utilities Last commit date
Array_Utility.php 3 years ago Coupon_Utility.php 5 months ago Encryption_Utility.php 2 years ago Helper.php 4 months ago Money_Utility.php 3 years ago Order_Ajax_Authorization.php 2 months ago Performance_Logger.php 1 year ago String_Utility.php 9 months ago Token_Scope_Utility.php 5 months ago
Coupon_Utility.php
704 lines
1 <?php
2 /**
3 * WooCommerce Square
4 *
5 * This source file is subject to the GNU General Public License v3.0
6 * that is bundled with this package in the file license.txt.
7 * It is also available through the world-wide-web at this URL:
8 * http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0 or later
9 * If you did not receive a copy of the license and are unable to
10 * obtain it through the world-wide-web, please send an email
11 * to license@woocommerce.com so we can send you a copy immediately.
12 *
13 * DISCLAIMER
14 *
15 * Do not edit or add to this file if you wish to upgrade WooCommerce Square to newer
16 * versions in the future. If you wish to customize WooCommerce Square for your
17 * needs please refer to https://docs.woocommerce.com/document/woocommerce-square/
18 *
19 * @author WooCommerce
20 * @copyright Copyright: (c) 2019, Automattic, Inc.
21 * @license http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0 or later
22 */
23
24 namespace WooCommerce\Square\Utilities;
25
26 defined( 'ABSPATH' ) || exit;
27
28 use WooCommerce\Square\API;
29 use WooCommerce\Square\Handlers\Product;
30 use Square\Models;
31 use Square\Models\CatalogObjectType;
32 use Square\Models\CatalogDiscountType;
33
34 /**
35 * Map a Square Coupon/Discount to a WooCommerce Coupon.
36 *
37 * @since 5.3.0
38 */
39 class Coupon_Utility {
40
41 /**
42 * The Square API bearer token.
43 *
44 * @var string
45 */
46 protected static $bearer_token = '';
47
48 /**
49 * Whether to use the Square sandbox environment.
50 *
51 * @var bool
52 */
53 protected static $is_sandbox = false;
54
55 /**
56 * The Square Discount object.
57 *
58 * @var Models\CatalogObject
59 */
60 protected static $discount_object;
61
62 /**
63 * The Square Pricing Rule and Product Set objects.
64 *
65 * @var Models\CatalogObject
66 */
67 protected static $pricing_rule_object;
68
69 /**
70 * The Square Product Set object.
71 *
72 * @var Models\CatalogObject
73 */
74 protected static $product_set_object;
75
76 /**
77 * Check if Square discount codes are enabled (setting + filter).
78 * Scope is not checked here; use Token_Scope_Utility in admin for merchant notices only.
79 *
80 * @since 5.3.0
81 *
82 * @return bool True if Square discount codes should be processed.
83 */
84 public static function is_square_discount_codes_enabled() {
85 $square_settings = get_option( 'wc_square_settings', array() );
86 $from_setting = ! array_key_exists( 'enable_square_discount_codes', $square_settings ) || 'yes' === $square_settings['enable_square_discount_codes'];
87
88 /**
89 * Filters whether Square discount codes should be processed.
90 *
91 * @since 5.3.0
92 *
93 * @param bool $enable_square_discount_codes Whether Square discount codes should be processed. Default follows Square settings.
94 */
95 return (bool) apply_filters( 'woocommerce_square_enable_discount_codes', $from_setting );
96 }
97
98 /**
99 * Remove a coupon from the cart by code (finds the applied code that matches and removes it).
100 *
101 * @since 5.3.0
102 *
103 * @param string $coupon_code The coupon code to remove (matched with wc_is_same_coupon).
104 * @return bool True if the coupon was found and removed, false otherwise.
105 */
106 public static function remove_coupon_from_cart( $coupon_code ) {
107 $cart = WC()->cart;
108 if ( ! $cart ) {
109 return false;
110 }
111 foreach ( $cart->get_applied_coupons() as $applied_code ) {
112 if ( wc_is_same_coupon( $applied_code, $coupon_code ) ) {
113 $cart->remove_coupon( $applied_code );
114 return true;
115 }
116 }
117 return false;
118 }
119
120 /**
121 * Check if a coupon code is in the cart's applied coupons.
122 *
123 * @since 5.3.0
124 *
125 * @param string $coupon_code The coupon code to check.
126 * @return bool True if the coupon is applied to the cart.
127 */
128 public static function is_coupon_in_applied_cart( $coupon_code ) {
129 $cart = WC()->cart;
130 if ( ! $cart ) {
131 return false;
132 }
133 foreach ( $cart->get_applied_coupons() as $applied_code ) {
134 if ( wc_is_same_coupon( $applied_code, $coupon_code ) ) {
135 return true;
136 }
137 }
138 return false;
139 }
140
141 /**
142 * Build a map of cart item key => catalog_object_id and name for matching Square line items to cart.
143 *
144 * @since 5.3.0
145 *
146 * @param \WC_Cart $cart WooCommerce cart.
147 * @return array<string, array{catalog_object_id: string, name: string}> Cart key => lookup data.
148 */
149 public static function get_cart_items_by_key( $cart ) {
150 $map = array();
151 foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
152 $product = $cart_item['data'];
153 $map[ $cart_item_key ] = array(
154 'catalog_object_id' => $product->get_meta( Product::SQUARE_VARIATION_ID_META_KEY ),
155 'name' => $product->get_name(),
156 );
157 }
158 return $map;
159 }
160
161 /**
162 * Find the WooCommerce cart item key that corresponds to a Square order line item.
163 * Matches by catalog object ID first, then by product name.
164 *
165 * @since 5.3.0
166 *
167 * @param array $square_line_item Line item from Square API response.
168 * @param array $cart_items_by_key Map from get_cart_items_by_key().
169 * @return string|null Cart item key or null if no match.
170 */
171 public static function match_square_line_to_cart_key( $square_line_item, $cart_items_by_key ) {
172 if ( ! empty( $square_line_item['catalog_object_id'] ) ) {
173 foreach ( $cart_items_by_key as $cart_key => $info ) {
174 if ( $info['catalog_object_id'] === $square_line_item['catalog_object_id'] ) {
175 return $cart_key;
176 }
177 }
178 }
179
180 if ( ! empty( $square_line_item['name'] ) ) {
181 foreach ( $cart_items_by_key as $cart_key => $info ) {
182 if ( $info['name'] === $square_line_item['name'] ) {
183 return $cart_key;
184 }
185 }
186 }
187
188 return null;
189 }
190
191 /**
192 * Get the transient key for caching discount code data.
193 *
194 * @since 5.3.0
195 *
196 * @param string $discount_code The discount code.
197 * @return string Transient key.
198 */
199 public static function get_discount_code_transient_key( $discount_code ) {
200 return 'square_discount_code_' . md5( strtolower( $discount_code ) );
201 }
202
203 /**
204 * Sentinel key in transient value when the discount code was looked up and not found.
205 * get_transient() returns false when the key is missing, so we store an array to distinguish "not found" from "not cached".
206 *
207 * @var string
208 */
209 const CACHE_SENTINEL_NOT_FOUND = '__not_found';
210
211 /**
212 * Cache discount code details.
213 * Uses WordPress transients to cache discount code data for 15 minutes.
214 *
215 * @since 5.3.0
216 *
217 * @param string $discount_code The discount code.
218 * @param array|null $code_details The discount code details to cache. Null if not found.
219 */
220 public static function set_cache_discount_code( $discount_code, $code_details ) {
221 $transient_key = self::get_discount_code_transient_key( $discount_code );
222
223 // Cache for 15 minutes. Store a sentinel array when not found so we can tell "not found" from "transient missing".
224 $cache_value = null === $code_details ? array( self::CACHE_SENTINEL_NOT_FOUND => true ) : $code_details;
225 set_transient( $transient_key, $cache_value, 15 * MINUTE_IN_SECONDS );
226 }
227
228 /**
229 * Retrieve cached discount code details.
230 *
231 * @since 5.3.0
232 *
233 * @param string $discount_code The discount code.
234 * @return array|null|false Cached discount code details, false if cached as "not found", or null if not cached.
235 */
236 public static function get_cache_discount_code( $discount_code ) {
237 $transient_key = self::get_discount_code_transient_key( $discount_code );
238 $cached = get_transient( $transient_key );
239
240 // Transient missing (expired or never set) → not cached.
241 if ( false === $cached ) {
242 return null;
243 }
244
245 // Explicitly cached as "not found" (sentinel array).
246 if ( is_array( $cached ) && isset( $cached[ self::CACHE_SENTINEL_NOT_FOUND ] ) ) {
247 return false;
248 }
249
250 return $cached;
251 }
252
253 /**
254 * Clear cached discount code details.
255 *
256 * @since 5.3.0
257 *
258 * @param string $discount_code The discount code.
259 */
260 public static function clear_cache_discount_code( $discount_code ) {
261 $transient_key = self::get_discount_code_transient_key( $discount_code );
262 delete_transient( $transient_key );
263 }
264
265 /**
266 * Retrieve discount code from the Square API.
267 * Uses caching to avoid repeated API calls for the same code.
268 *
269 * @since 5.3.0
270 *
271 * @param string $discount_code The discount code to retrieve.
272 * @return array|null Discount code details, or null if not found.
273 */
274 public static function get_discount_code( $discount_code ) {
275 $cached = self::get_cache_discount_code( $discount_code );
276 if ( is_array( $cached ) ) {
277 return $cached;
278 }
279
280 if ( false === $cached ) {
281 // Cached as "not found"; avoid redundant API call.
282 return null;
283 }
284
285 $data = self::search_discount_codes_via_api( $discount_code );
286
287 if ( null === $data || empty( $data['discount_codes'] ) ) {
288 self::set_cache_discount_code( $discount_code, null );
289 return null;
290 }
291
292 $code = self::find_valid_discount_code( $data['discount_codes'], $discount_code );
293 if ( null === $code ) {
294 self::set_cache_discount_code( $discount_code, null );
295 return null;
296 }
297
298 self::set_cache_discount_code( $discount_code, $code );
299 return $code;
300 }
301
302 /**
303 * Get Square discount code ID by coupon code.
304 *
305 * @since 5.3.0
306 *
307 * @param string $coupon_code The coupon code to search for.
308 * @return string|null The discount code ID or null if not found.
309 */
310 public static function get_square_discount_code_id_by_code( $coupon_code ) {
311 $code = self::get_discount_code( $coupon_code );
312 return ( $code && isset( $code['id'] ) ) ? $code['id'] : null;
313 }
314
315 /**
316 * Find and validate a matching discount code from API response.
317 *
318 * @since 5.3.0
319 *
320 * @param array $discount_codes Array of discount codes from API response.
321 * @param string $coupon_code The coupon code to find and validate.
322 * @return array|null The matching and valid discount code, or null if not found or invalid.
323 */
324 private static function find_valid_discount_code( $discount_codes, $coupon_code ) {
325 if ( empty( $discount_codes ) || ! is_array( $discount_codes ) ) {
326 return null;
327 }
328
329 $current_time = time();
330
331 foreach ( $discount_codes as $code ) {
332 if ( ! isset( $code['code'] ) || strtoupper( $code['code'] ) !== strtoupper( $coupon_code ) ) {
333 continue;
334 }
335
336 $valid_from = isset( $code['valid_from'] ) ? strtotime( $code['valid_from'] ) : null;
337 $expires_at = isset( $code['expires_at'] ) ? strtotime( $code['expires_at'] ) : null;
338
339 if ( null !== $valid_from && $valid_from > $current_time ) {
340 continue;
341 }
342 if ( null !== $expires_at && $expires_at < $current_time ) {
343 continue;
344 }
345
346 return $code;
347 }
348
349 return null;
350 }
351
352 /**
353 * Search for discount codes via Square API.
354 *
355 * @since 5.3.0
356 *
357 * @param string $coupon_code The coupon code to search for.
358 * @param int $timeout Request timeout in seconds. Default 30.
359 * @return array|null Response data with 'discount_codes' key, or null on error.
360 */
361 private static function search_discount_codes_via_api( $coupon_code, $timeout = 30 ) {
362 $query = array(
363 'query' => array(
364 'filter' => array(
365 'code' => $coupon_code,
366 ),
367 ),
368 );
369
370 $result = self::square_api_post( 'discount-codes/search', $query, $timeout );
371
372 if ( is_wp_error( $result ) ) {
373 if ( function_exists( 'wc_square' ) ) {
374 wc_square()->log( sprintf( 'Error searching for discount code %s: %s', $coupon_code, $result->get_error_message() ), 'square-coupons' );
375 }
376 return null;
377 }
378
379 return isset( $result['body'] ) ? $result['body'] : null;
380 }
381
382 /**
383 * Get Square API credentials for direct HTTP requests.
384 * Used for endpoints not available in the Square SDK (e.g., discount codes search).
385 * Credentials are cached in static properties to avoid redundant fetches during a request.
386 *
387 * @since 5.3.0
388 *
389 * @return array|null Array with 'access_token', 'is_sandbox', and 'base_url', or null on error.
390 */
391 public static function get_square_api_credentials() {
392 // Return cached credentials if already set (credentials don't change during a request).
393 if ( ! empty( self::$bearer_token ) ) {
394 $base_url = 'https://connect.squareup' . ( self::$is_sandbox ? 'sandbox' : '' ) . '.com/v2';
395 return array(
396 'access_token' => self::$bearer_token,
397 'is_sandbox' => self::$is_sandbox,
398 'base_url' => $base_url,
399 );
400 }
401
402 if ( ! function_exists( 'wc_square' ) ) {
403 return null;
404 }
405
406 $settings_handler = wc_square()->get_settings_handler();
407 if ( ! $settings_handler ) {
408 return null;
409 }
410
411 $bearer_token = $settings_handler->get_access_token();
412 $is_sandbox = $settings_handler->is_sandbox();
413
414 if ( empty( $bearer_token ) ) {
415 return null;
416 }
417
418 // Cache credentials in static properties for subsequent calls.
419 self::$bearer_token = $bearer_token;
420 self::$is_sandbox = $is_sandbox;
421
422 $base_url = 'https://connect.squareup' . ( $is_sandbox ? 'sandbox' : '' ) . '.com/v2';
423
424 return array(
425 'access_token' => $bearer_token,
426 'is_sandbox' => $is_sandbox,
427 'base_url' => $base_url,
428 );
429 }
430
431 /**
432 * Make a POST request to the Square API.
433 * Wrapper for direct HTTP calls to avoid duplicating credential and request logic.
434 *
435 * @since 5.3.0
436 *
437 * @param string $path API path relative to base URL (e.g. 'orders/calculate' or 'discount-codes/search').
438 * @param array $body Request body as array (will be JSON-encoded).
439 * @param int $timeout Request timeout in seconds. Default 30.
440 * @return array|WP_Error Decoded response body and response code on success, WP_Error on failure.
441 */
442 public static function square_api_post( $path, $body, $timeout = 30 ) {
443 $credentials = self::get_square_api_credentials();
444 if ( null === $credentials ) {
445 return new \WP_Error( 'missing_credentials', __( 'Square API credentials are not configured.', 'woocommerce-square' ) );
446 }
447
448 $api_url = $credentials['base_url'] . '/' . ltrim( $path, '/' );
449
450 $response = wp_remote_post(
451 $api_url,
452 array(
453 'headers' => array(
454 'Authorization' => 'Bearer ' . $credentials['access_token'],
455 'Content-Type' => 'application/json',
456 'Square-Version' => '2025-01-23',
457 ),
458 'body' => wp_json_encode( $body ),
459 'timeout' => $timeout,
460 )
461 );
462
463 if ( is_wp_error( $response ) ) {
464 return $response;
465 }
466
467 $response_code = wp_remote_retrieve_response_code( $response );
468 $response_body = wp_remote_retrieve_body( $response );
469
470 if ( 200 !== $response_code ) {
471 $error_data = json_decode( $response_body, true );
472 $error_message = isset( $error_data['errors'] ) && is_array( $error_data['errors'] ) && ! empty( $error_data['errors'][0]['detail'] )
473 ? $error_data['errors'][0]['detail']
474 : wp_remote_retrieve_response_message( $response );
475
476 return new \WP_Error(
477 'api_error',
478 $error_message,
479 array(
480 'status' => $response_code,
481 'response' => $error_data,
482 )
483 );
484 }
485
486 $data = json_decode( $response_body, true );
487
488 return array(
489 'body' => $data,
490 'response_code' => $response_code,
491 );
492 }
493
494 /**
495 * Map a Square Discount Code to a WooCommerce Coupon array.
496 *
497 * This allows for the creation of manual WC_Coupon object mapped from the
498 * Square Discount code data provides.
499 *
500 * @since 5.3.0
501 *
502 * @param array $square_discount_code The Square discount code array.
503 * @return array|false The mapped WooCommerce coupon data. False if mapping fails.
504 */
505 public static function map_square_discount_code_to_woocommerce_coupon( $square_discount_code ) {
506 // Create cache key based on pricing rule ID and version.
507 $pricing_rule_id = $square_discount_code['pricing_rule_id'];
508 $pricing_rule_version = $square_discount_code['pricing_rule_version'];
509 $cache_key = 'square_coupon_mapping_' . md5( $pricing_rule_id . '_' . $pricing_rule_version );
510
511 // Check cache first.
512 $cached = get_transient( $cache_key );
513 if ( false !== $cached && is_array( $cached ) ) {
514 // Update code in case it's different (though it should be the same for same pricing rule).
515 $cached['code'] = $square_discount_code['code'];
516 return $cached;
517 }
518
519 // Configure the API for use.
520 // get_square_api_credentials() will cache credentials in static properties.
521 $credentials = self::get_square_api_credentials();
522 if ( null === $credentials ) {
523 return false;
524 }
525
526 // Retrieve the pricing rule object.
527 $pricing_rule_objects = self::request_pricing_rule_objects( $pricing_rule_id, $pricing_rule_version );
528
529 if ( ! $pricing_rule_objects ) {
530 // Unable to retrieve pricing rule details/objects. Coupon invalid/incomplete.
531 return false;
532 }
533
534 // Map the Square coupon format to the WC coupon format.
535 // product_ids is empty: eligibility is determined by Square (CalculateOrder);
536 // amount is 0: we override amounts per line later in Coupons::override_discount_amount_with_square().
537 $wc_coupon = array(
538 'code' => $square_discount_code['code'],
539 'discount_type' => self::map_discount_type(),
540 'amount' => 0,
541 'product_ids' => array(),
542 );
543
544 // Cache the result for 1 hour (pricing rules don't change frequently).
545 set_transient( $cache_key, $wc_coupon, HOUR_IN_SECONDS );
546
547 return $wc_coupon;
548 }
549
550 /**
551 * Get the Square CatalogDiscount object ID for a pricing rule (used to match order.discounts in API responses).
552 * Results are cached by pricing_rule_id and version to avoid repeated API calls.
553 *
554 * @since 5.3.0
555 *
556 * @param string $pricing_rule_id The Square pricing rule ID.
557 * @param int $pricing_rule_version The Square pricing rule version.
558 * @return string|null The discount catalog object ID, or null if not found.
559 */
560 public static function get_discount_catalog_id_for_pricing_rule( $pricing_rule_id, $pricing_rule_version ) {
561 if ( empty( $pricing_rule_id ) ) {
562 return null;
563 }
564 $cache_key = 'square_discount_catalog_id_' . md5( $pricing_rule_id . '_' . (int) $pricing_rule_version );
565 $cached = get_transient( $cache_key );
566 if ( false !== $cached && is_string( $cached ) ) {
567 return $cached;
568 }
569 if ( ! self::request_pricing_rule_objects( $pricing_rule_id, $pricing_rule_version ) ) {
570 return null;
571 }
572 $discount_id = null;
573 if ( self::$discount_object instanceof Models\CatalogObject ) {
574 $discount_id = self::$discount_object->getId();
575 }
576 if ( $discount_id ) {
577 set_transient( $cache_key, $discount_id, HOUR_IN_SECONDS );
578 }
579
580 return $discount_id;
581 }
582
583 /**
584 * Request the pricing rule and related objects from Square.
585 *
586 * @since 5.3.0
587 *
588 * @param string $pricing_rule_id The Square pricing rule ID.
589 * @param int $pricing_rule_version The Square pricing rule version.
590 *
591 * @return bool True on success, false on failure.
592 */
593 protected static function request_pricing_rule_objects( $pricing_rule_id, $pricing_rule_version ) {
594 // Ensure credentials are available.
595 $credentials = self::get_square_api_credentials();
596 if ( null === $credentials ) {
597 return false;
598 }
599
600 // Retrieve the pricing rule object.
601 $request = new API( $credentials['access_token'], $credentials['is_sandbox'] );
602 $response = $request->retrieve_catalog_object( $pricing_rule_id, true, $pricing_rule_version );
603
604 if ( ! $response->get_data() instanceof \Square\Models\RetrieveCatalogObjectResponse ) {
605 // Unable to retrieve pricing rule details.
606 return false;
607 }
608
609 $pricing_rule = $response->get_data()->getObject();
610 if ( ! $pricing_rule instanceof Models\CatalogObject
611 || $pricing_rule->getType() !== CatalogObjectType::PRICING_RULE ) {
612 // Invalid pricing rule object.
613 return false;
614 }
615
616 $related_objects = $response->get_data()->getRelatedObjects();
617 if ( empty( $related_objects ) || ! is_array( $related_objects ) ) {
618 // No related objects found.
619 return false;
620 }
621
622 $discount_object = self::get_related_objects_by_type( $related_objects, CatalogObjectType::DISCOUNT );
623 if ( empty( $discount_object ) || ! $discount_object[0] instanceof Models\CatalogObject ) {
624 // No discount object found.
625 return false;
626 }
627
628 $product_set_object = self::get_related_objects_by_type( $related_objects, CatalogObjectType::PRODUCT_SET );
629 if ( empty( $product_set_object ) || ! $product_set_object[0] instanceof Models\CatalogObject ) {
630 /*
631 * No product set object found.
632 *
633 * Note: A pricing rule is always associated with a product set. If the
634 * pricing rule applies to all products. The product set will include the
635 * `allProducts` field set to true.
636 */
637
638 return false;
639 }
640
641 self::$pricing_rule_object = $pricing_rule;
642 self::$discount_object = $discount_object[0];
643 self::$product_set_object = $product_set_object[0];
644
645 return true;
646 }
647
648 /**
649 * Filter related objects by type.
650 *
651 * @since 5.3.0
652 *
653 * @param Models\CatalogObject[] $related_objects The related objects.
654 * @param string $type The desired object type.
655 * @return Models\CatalogObject[] The filtered related objects.
656 */
657 protected static function get_related_objects_by_type( $related_objects, $type ) {
658 $filtered_objects = array();
659
660 foreach ( $related_objects as $object ) {
661 if (
662 $object instanceof Models\CatalogObject
663 && $object->getType() === $type
664 && $object->getIsDeleted() === false
665 ) {
666 $filtered_objects[] = $object;
667 }
668 }
669
670 return $filtered_objects;
671 }
672
673 /**
674 * Map the Square discount type to the WooCommerce coupon discount type.
675 *
676 * @since 5.3.0
677 *
678 * @return string The mapped discount type.
679 * @throws \Exception If the discount type is unsupported.
680 */
681 protected static function map_discount_type() {
682 $sq_discount_type = self::$discount_object->getDiscountData()->getDiscountType();
683 $sq_is_all_products = self::$product_set_object->getProductSetData()->getAllProducts();
684
685 switch ( $sq_discount_type ) {
686 case CatalogDiscountType::FIXED_AMOUNT:
687 if ( $sq_is_all_products ) {
688 return 'fixed_cart';
689 }
690 return 'fixed_product';
691 case CatalogDiscountType::FIXED_PERCENTAGE:
692 return 'percent';
693 default:
694 throw new \Exception(
695 sprintf(
696 /* translators: 1: Square discount type. */
697 esc_html__( 'Unsupported discount type: %s', 'woocommerce-square' ),
698 esc_html( $sq_discount_type )
699 )
700 );
701 }
702 }
703 }
704