<?php declare(strict_types = 1); namespace Automattic\WooCommerce\GoogleListingsAndAds\Coupon; use Automattic\WooCommerce\GoogleListingsAndAds\Exception\InvalidMeta; use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service; use Automattic\WooCommerce\GoogleListingsAndAds\PluginHelper; use BadMethodCallException; use WC_Coupon; defined( 'ABSPATH' ) || exit(); /** * Class CouponMetaHandler * * @package Automattic\WooCommerce\GoogleListingsAndAds\Coupon * * @method update_synced_at( WC_Coupon $coupon, $value ) * @method delete_synced_at( WC_Coupon $coupon ) * @method get_synced_at( WC_Coupon $coupon ): int|null * @method update_google_ids( WC_Coupon $coupon, array $value ) * @method delete_google_ids( WC_Coupon $coupon ) * @method get_google_ids( WC_Coupon $coupon ): array|null * @method update_visibility( WC_Coupon $coupon, $value ) * @method delete_visibility( WC_Coupon $coupon ) * @method get_visibility( WC_Coupon $coupon ): string|null * @method update_errors( WC_Coupon $coupon, array $value ) * @method delete_errors( WC_Coupon $coupon ) * @method get_errors( WC_Coupon $coupon ): array|null * @method update_failed_sync_attempts( WC_Coupon $coupon, int $value ) * @method delete_failed_sync_attempts( WC_Coupon $coupon ) * @method get_failed_sync_attempts( WC_Coupon $coupon ): int|null * @method update_sync_failed_at( WC_Coupon $coupon, int $value ) * @method delete_sync_failed_at( WC_Coupon $coupon ) * @method get_sync_failed_at( WC_Coupon $coupon ): int|null * @method update_sync_status( WC_Coupon $coupon, string $value ) * @method delete_sync_status( WC_Coupon $coupon ) * @method get_sync_status( WC_Coupon $coupon ): string|null * @method update_mc_status( WC_Coupon $coupon, string $value ) * @method delete_mc_status( WC_Coupon $coupon ) * @method get_mc_status( WC_Coupon $coupon ): string|null */ class CouponMetaHandler implements Service { use PluginHelper; public const KEY_SYNCED_AT = 'synced_at'; public const KEY_GOOGLE_IDS = 'google_ids'; public const KEY_VISIBILITY = 'visibility'; public const KEY_ERRORS = 'errors'; public const KEY_FAILED_SYNC_ATTEMPTS = 'failed_sync_attempts'; public const KEY_SYNC_FAILED_AT = 'sync_failed_at'; public const KEY_SYNC_STATUS = 'sync_status'; public const KEY_MC_STATUS = 'mc_status'; protected const TYPES = [ self::KEY_SYNCED_AT => 'int', self::KEY_GOOGLE_IDS => 'array', self::KEY_VISIBILITY => 'string', self::KEY_ERRORS => 'array', self::KEY_FAILED_SYNC_ATTEMPTS => 'int', self::KEY_SYNC_FAILED_AT => 'int', self::KEY_SYNC_STATUS => 'string', self::KEY_MC_STATUS => 'string', ]; /** * * @param string $name * @param mixed $arguments * * @return mixed * * @throws BadMethodCallException If the method that's called doesn't exist. * @throws InvalidMeta If the meta key is invalid. */ public function __call( string $name, $arguments ) { $found_matches = preg_match( '/^([a-z]+)_([\w\d]+)$/i', $name, $matches ); if ( ! $found_matches ) { throw new BadMethodCallException( sprintf( 'The method %s does not exist in class CouponMetaHandler', $name ) ); } [ $function_name, $method, $key ] = $matches; // validate the method if ( ! in_array( $method, [ 'update', 'delete', 'get', ], true ) ) { throw new BadMethodCallException( sprintf( 'The method %s does not exist in class CouponMetaHandler', $function_name ) ); } // set the value as the third argument if method is `update` if ( 'update' === $method ) { $arguments[2] = $arguments[1]; } // set the key as the second argument $arguments[1] = $key; return call_user_func_array( [ $this, $method, ], $arguments ); } /** * * @param WC_Coupon $coupon * @param string $key * @param mixed $value * * @throws InvalidMeta If the meta key is invalid. */ public function update( WC_Coupon $coupon, string $key, $value ) { self::validate_meta_key( $key ); if ( isset( self::TYPES[ $key ] ) ) { if ( in_array( self::TYPES[ $key ], [ 'bool', 'boolean', ], true ) ) { $value = wc_bool_to_string( $value ); } else { settype( $value, self::TYPES[ $key ] ); } } $coupon->update_meta_data( $this->prefix_meta_key( $key ), $value ); $coupon->save_meta_data(); } /** * * @param WC_Coupon $coupon * @param string $key * * @throws InvalidMeta If the meta key is invalid. */ public function delete( WC_Coupon $coupon, string $key ) { self::validate_meta_key( $key ); $coupon->delete_meta_data( $this->prefix_meta_key( $key ) ); $coupon->save_meta_data(); } /** * * @param WC_Coupon $coupon * @param string $key * * @return mixed The value, or null if the meta key doesn't exist. * * @throws InvalidMeta If the meta key is invalid. */ public function get( WC_Coupon $coupon, string $key ) { self::validate_meta_key( $key ); $value = null; if ( $coupon->meta_exists( $this->prefix_meta_key( $key ) ) ) { $value = $coupon->get_meta( $this->prefix_meta_key( $key ), true ); if ( isset( self::TYPES[ $key ] ) && in_array( self::TYPES[ $key ], [ 'bool', 'boolean', ], true ) ) { $value = wc_string_to_bool( $value ); } } return $value; } /** * * @param string $key * * @throws InvalidMeta If the meta key is invalid. */ protected static function validate_meta_key( string $key ) { if ( ! self::is_meta_key_valid( $key ) ) { do_action( 'woocommerce_gla_error', sprintf( 'Coupon meta key is invalid: %s', $key ), __METHOD__ ); throw InvalidMeta::invalid_key( $key ); } } /** * * @param string $key * * @return bool Whether the meta key is valid. */ public static function is_meta_key_valid( string $key ): bool { return isset( self::TYPES[ $key ] ); } /** * Returns all available meta keys. * * @return array */ public static function get_all_meta_keys(): array { return array_keys( self::TYPES ); } }