From 25db8192d7029b6a89b0bbd4b508c467495f3d22 Mon Sep 17 00:00:00 2001 From: Jorge M Date: Wed, 25 Oct 2023 18:10:29 +0200 Subject: [PATCH 001/135] WIP --- .../GoogleListingsAndAdsPlugin.php | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/Infrastructure/GoogleListingsAndAdsPlugin.php b/src/Infrastructure/GoogleListingsAndAdsPlugin.php index 315d230d67..0c53b96f8f 100644 --- a/src/Infrastructure/GoogleListingsAndAdsPlugin.php +++ b/src/Infrastructure/GoogleListingsAndAdsPlugin.php @@ -32,6 +32,12 @@ final class GoogleListingsAndAdsPlugin implements Plugin { */ private $registered_services; + /** + * The client ID. + * @var string + */ + private $client_id; + /** * GoogleListingsAndAdsPlugin constructor. * @@ -115,6 +121,12 @@ function() { } ); + add_action( 'login_form_jetpack_json_api_authorization', array( $this, 'login_form_json_api_authorization' ) ); + + add_filter('jetpack_xmlrpc_test_connection_response', function (){ + return '1.40'; + }); + } /** @@ -143,4 +155,94 @@ protected function maybe_register_services(): void { $registered = true; } + + /** + * Handles the login action for Authorizing the JSON API + */ + public function login_form_json_api_authorization() { + add_action( 'wp_login', array( $this, 'store_json_api_authorization_token' ), 10, 2 ); + add_action( 'login_form', array( $this, 'preserve_action_in_login_form_for_json_api_authorization' ) ); + add_filter( 'site_url', array( $this, 'post_login_form_to_signed_url' ), 10, 3 ); + } + + /** + * If someone logs in to approve API access, store the Access Code in usermeta. + * + * @param string $user_login Unused. + * @param WP_User $user User logged in. + */ + public function store_json_api_authorization_token( $user_login, $user ) { + $data = json_decode( base64_decode( stripslashes( $_REQUEST['data'] ) ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode + $this->client_id = $data->client_id; + add_filter( 'login_redirect', array( $this, 'add_token_to_login_redirect_json_api_authorization' ), 10, 3 ); + add_filter( 'allowed_redirect_hosts', array( $this, 'allow_wpcom_public_api_domain' ) ); + $token = wp_generate_password( 32, false ); + update_user_meta( $user->ID, 'jetpack_json_api_' . $this->client_id, $token ); + } + + /** + * Make sure the POSTed request is handled by the same action. + */ + public function preserve_action_in_login_form_for_json_api_authorization() { + $http_host = isset( $_SERVER['HTTP_HOST'] ) ? wp_unslash( $_SERVER['HTTP_HOST'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- escaped with esc_url below. + $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- escaped with esc_url below. + echo "\n"; + echo "\n"; + } + + /** + * Make sure the login form is POSTed to the signed URL so we can reverify the request. + * + * @param string $url Redirect URL. + * @param string $path Path. + * @param string $scheme URL Scheme. + */ + public function post_login_form_to_signed_url( $url, $path, $scheme ) { + if ( 'wp-login.php' !== $path || ( 'login_post' !== $scheme && 'login' !== $scheme ) ) { + return $url; + } + $query_string = isset( $_SERVER['QUERY_STRING'] ) ? wp_unslash( $_SERVER['QUERY_STRING'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + $parsed_url = wp_parse_url( $url ); + $url = strtok( $url, '?' ); + $url = "$url?{$query_string}"; + if ( ! empty( $parsed_url['query'] ) ) { + $url .= "&{$parsed_url['query']}"; + } + + return $url; + } + + /** + * Add the Access Code details to the public-api.wordpress.com redirect. + * + * @param string $redirect_to URL. + * @param string $original_redirect_to URL. + * @param WP_User $user WP_User for the redirect. + * + * @return string + */ + public function add_token_to_login_redirect_json_api_authorization( $redirect_to, $original_redirect_to, $user ) { + return add_query_arg( + urlencode_deep( + array( + 'jetpack-code' => get_user_meta( $user->ID, 'jetpack_json_api_' . $this->client_id, true ), + 'jetpack-user-id' => (int) $user->ID, + 'jetpack-state' => '', + ) + ), + $redirect_to + ); + } + + /** + * Add public-api.wordpress.com to the safe redirect allowed list - only added when someone allows API access. + * + * To be used with a filter of allowed domains for a redirect. + * + * @param array $domains Allowed WP.com Environments. + */ + public function allow_wpcom_public_api_domain( $domains ) { + $domains[] = 'public-api.wordpress.com'; + return $domains; + } } From 81918f57ce02aa7005c451e97cb96be8f15425dc Mon Sep 17 00:00:00 2001 From: Jorge M Date: Mon, 6 Nov 2023 17:45:38 +0100 Subject: [PATCH 002/135] Add Missing Jetpack functions --- src/Integration/JetpackWPCOM.php | 368 +++++++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 src/Integration/JetpackWPCOM.php diff --git a/src/Integration/JetpackWPCOM.php b/src/Integration/JetpackWPCOM.php new file mode 100644 index 0000000000..e112d82233 --- /dev/null +++ b/src/Integration/JetpackWPCOM.php @@ -0,0 +1,368 @@ +verify_json_api_authorization_request(); + add_action( 'wp_login', [ $this, 'store_json_api_authorization_token' ], 10, 2 ); + add_action( 'login_message', [ $this, 'login_message_json_api_authorization' ] ); + add_action( 'login_form', [ $this, 'preserve_action_in_login_form_for_json_api_authorization' ] ); + add_filter( 'site_url', [ $this, 'post_login_form_to_signed_url' ], 10, 3 ); + } + + /** + * If someone logs in to approve API access, store the Access Code in usermeta. + * + * @param string $user_login Unused. + * @param WP_User $user User logged in. + */ + /** + * If someone logs in to approve API access, store the Access Code in usermeta. + * + * @param string $user_login Unused. + * @param WP_User $user User logged in. + */ + public function store_json_api_authorization_token( $user_login, $user ) { + add_filter( 'login_redirect', [ $this, 'add_token_to_login_redirect_json_api_authorization' ], 10, 3 ); + add_filter( 'allowed_redirect_hosts', [ $this, 'allow_wpcom_public_api_domain' ] ); + $token = wp_generate_password( 32, false ); + update_user_meta( $user->ID, 'jetpack_json_api_' . $this->json_api_authorization_request['client_id'], $token ); + } + + /** + * Make sure the POSTed request is handled by the same action. + */ + public function preserve_action_in_login_form_for_json_api_authorization() { + $http_host = isset( $_SERVER['HTTP_HOST'] ) ? wp_unslash( $_SERVER['HTTP_HOST'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- escaped with esc_url below. + $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- escaped with esc_url below. + echo "\n"; + echo "\n"; + } + + /** + * Make sure the login form is POSTed to the signed URL so we can reverify the request. + * + * @param string $url Redirect URL. + * @param string $path Path. + * @param string $scheme URL Scheme. + */ + public function post_login_form_to_signed_url( $url, $path, $scheme ) { + if ( 'wp-login.php' !== $path || ( 'login_post' !== $scheme && 'login' !== $scheme ) ) { + return $url; + } + $query_string = isset( $_SERVER['QUERY_STRING'] ) ? wp_unslash( $_SERVER['QUERY_STRING'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + $parsed_url = wp_parse_url( $url ); + $url = strtok( $url, '?' ); + $url = "$url?{$query_string}"; + if ( ! empty( $parsed_url['query'] ) ) { + $url .= "&{$parsed_url['query']}"; + } + + return $url; + } + + /** + * Add the Access Code details to the public-api.wordpress.com redirect. + * + * @param string $redirect_to URL. + * @param string $original_redirect_to URL. + * @param WP_User $user WP_User for the redirect. + * + * @return string + */ + public function add_token_to_login_redirect_json_api_authorization( $redirect_to, $original_redirect_to, $user ) { + return add_query_arg( + urlencode_deep( + [ + 'jetpack-code' => get_user_meta( $user->ID, 'jetpack_json_api_' . $this->json_api_authorization_request['client_id'], true ), + 'jetpack-user-id' => (int) $user->ID, + 'jetpack-state' => $this->json_api_authorization_request['state'], + ] + ), + $redirect_to + ); + } + + /** + * Add public-api.wordpress.com to the safe redirect allowed list - only added when someone allows API access. + * + * To be used with a filter of allowed domains for a redirect. + * + * @param array $domains Allowed WP.com Environments. + */ + public function allow_wpcom_public_api_domain( $domains ) { + $domains[] = 'public-api.wordpress.com'; + return $domains; + } + + /** + * Check if the redirect is encoded. + * + * @param string $redirect_url Redirect URL. + * + * @return bool If redirect has been encoded. + */ + public static function is_redirect_encoded( $redirect_url ) { + return preg_match( '/https?%3A%2F%2F/i', $redirect_url ) > 0; + } + + /** + * HTML for the JSON API authorization notice. + * + * @return string + */ + public function login_message_json_api_authorization() { + return '

' . sprintf( + /* translators: Name/image of the client requesting authorization */ + esc_html__( '%s wants to access your site’s data. Log in to authorize that access.', 'google-listings-and-ads' ), + '' . esc_html( $this->json_api_authorization_request['client_title'] ) . '' + ) . '

'; + } + + /** + * Verifies the request by checking the signature + * + * @since 4.6.0 Method was updated to use `$_REQUEST` instead of `$_GET` and `$_POST`. Method also updated to allow + * passing in an `$environment` argument that overrides `$_REQUEST`. This was useful for integrating with SSO. + * + * @param null|array $environment Value to override $_REQUEST. + */ + public function verify_json_api_authorization_request( $environment = null ) { + $environment = $environment === null + ? $_REQUEST // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- nonce verification handled later in function. + : $environment; + + list( $env_token,, $env_user_id ) = explode( ':', $environment['token'] ); + $token = ( new Tokens() )->get_access_token( $env_user_id, $env_token ); + if ( ! $token || empty( $token->secret ) ) { + wp_die( esc_html__( 'You must connect your Jetpack plugin to WordPress.com to use this feature.', 'google-listings-and-ads' ) ); + } + + $die_error = __( 'Someone may be trying to trick you into giving them access to your site. Or it could be you just encountered a bug :). Either way, please close this window.', 'google-listings-and-ads' ); + + // Host has encoded the request URL, probably as a result of a bad http => https redirect. + if ( self::is_redirect_encoded( esc_url_raw( wp_unslash( $_GET['redirect_to'] ) ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- no site changes, we're erroring out. + /** + * Jetpack authorisation request Error. + * + * @since 7.5.0 + */ + do_action( 'jetpack_verify_api_authorization_request_error_double_encode' ); + $die_error = sprintf( + /* translators: %s is a URL */ + __( 'Your site is incorrectly double-encoding redirects from http to https. This is preventing Jetpack from authenticating your connection. Please visit our support page for details about how to resolve this.', 'google-listings-and-ads' ), + esc_url( 'https://jetpack.com/support/double-encoding/' ) + ); + } + + $jetpack_signature = new Jetpack_Signature( $token->secret, (int) Jetpack_Options::get_option( 'time_diff' ) ); + + if ( isset( $environment['jetpack_json_api_original_query'] ) ) { + $signature = $jetpack_signature->sign_request( + $environment['token'], + $environment['timestamp'], + $environment['nonce'], + '', + 'GET', + $environment['jetpack_json_api_original_query'], + null, + true + ); + } else { + $signature = $jetpack_signature->sign_current_request( + [ + 'body' => null, + 'method' => 'GET', + ] + ); + } + + if ( ! $signature ) { + wp_die( + wp_kses( + $die_error, + [ + 'a' => [ + 'href' => [], + ], + ] + ) + ); + } elseif ( is_wp_error( $signature ) ) { + wp_die( + wp_kses( + $die_error, + [ + 'a' => [ + 'href' => [], + ], + ] + ) + ); + } elseif ( ! hash_equals( $signature, $environment['signature'] ) ) { + if ( is_ssl() ) { + // If we signed an HTTP request on the Jetpack Servers, but got redirected to HTTPS by the local blog, check the HTTP signature as well. + $signature = $jetpack_signature->sign_current_request( + [ + 'scheme' => 'http', + 'body' => null, + 'method' => 'GET', + ] + ); + if ( ! $signature || is_wp_error( $signature ) || ! hash_equals( $signature, $environment['signature'] ) ) { + wp_die( + wp_kses( + $die_error, + [ + 'a' => [ + 'href' => [], + ], + ] + ) + ); + } + } else { + wp_die( + wp_kses( + $die_error, + [ + 'a' => [ + 'href' => [], + ], + ] + ) + ); + } + } + + $timestamp = (int) $environment['timestamp']; + $nonce = stripslashes( (string) $environment['nonce'] ); + + if ( ! $this->connection_manager ) { + $this->connection_manager = new Connection_Manager(); + } + + if ( ! ( new Nonce_Handler() )->add( $timestamp, $nonce ) ) { + // De-nonce the nonce, at least for 5 minutes. + // We have to reuse this nonce at least once (used the first time when the initial request is made, used a second time when the login form is POSTed). + $old_nonce_time = get_option( "jetpack_nonce_{$timestamp}_{$nonce}" ); + if ( $old_nonce_time < time() - 300 ) { + wp_die( esc_html__( 'The authorization process expired. Please go back and try again.', 'google-listings-and-ads' ) ); + } + } + + $data = json_decode( base64_decode( stripslashes( $environment['data'] ) ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode + $data_filters = [ + 'state' => 'opaque', + 'client_id' => 'int', + 'client_title' => 'string', + 'client_image' => 'url', + ]; + + foreach ( $data_filters as $key => $sanitation ) { + if ( ! isset( $data->$key ) ) { + wp_die( + wp_kses( + $die_error, + [ + 'a' => [ + 'href' => [], + ], + ] + ) + ); + } + + switch ( $sanitation ) { + case 'int': + $this->json_api_authorization_request[ $key ] = (int) $data->$key; + break; + case 'opaque': + $this->json_api_authorization_request[ $key ] = (string) $data->$key; + break; + case 'string': + $this->json_api_authorization_request[ $key ] = wp_kses( (string) $data->$key, [] ); + break; + case 'url': + $this->json_api_authorization_request[ $key ] = esc_url_raw( (string) $data->$key ); + break; + } + } + + if ( empty( $this->json_api_authorization_request['client_id'] ) ) { + wp_die( + wp_kses( + $die_error, + [ + 'a' => [ + 'href' => [], + ], + ] + ) + ); + } + } +} From 05ab4727eb8258f5cef1e17006fffd8f87d00892 Mon Sep 17 00:00:00 2001 From: Jorge M Date: Mon, 6 Nov 2023 17:52:22 +0100 Subject: [PATCH 003/135] Add JetpackWPCOM to the service provider --- .../DependencyManagement/IntegrationServiceProvider.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Internal/DependencyManagement/IntegrationServiceProvider.php b/src/Internal/DependencyManagement/IntegrationServiceProvider.php index 571b6792e2..710e9fc5b7 100644 --- a/src/Internal/DependencyManagement/IntegrationServiceProvider.php +++ b/src/Internal/DependencyManagement/IntegrationServiceProvider.php @@ -11,6 +11,7 @@ use Automattic\WooCommerce\GoogleListingsAndAds\Integration\WooCommercePreOrders; use Automattic\WooCommerce\GoogleListingsAndAds\Integration\WooCommerceProductBundles; use Automattic\WooCommerce\GoogleListingsAndAds\Integration\YoastWooCommerceSeo; +use Automattic\WooCommerce\GoogleListingsAndAds\Integration\JetpackWPCOM; use Automattic\WooCommerce\GoogleListingsAndAds\Product\Attributes\AttributeManager; use Automattic\WooCommerce\GoogleListingsAndAds\Product\ProductHelper; use Automattic\WooCommerce\GoogleListingsAndAds\Proxies\WP; @@ -45,6 +46,7 @@ public function register(): void { $this->share_with_tags( WooCommerceBrands::class, WP::class ); $this->share_with_tags( WooCommerceProductBundles::class, AttributeManager::class ); $this->share_with_tags( WooCommercePreOrders::class, ProductHelper::class ); + $this->conditionally_share_with_tags( JetpackWPCOM::class ); $this->share_with_tags( IntegrationInitializer::class, From 6975f776364f38c754cf038942244f4430e5fcb5 Mon Sep 17 00:00:00 2001 From: Jorge M Date: Mon, 6 Nov 2023 17:53:01 +0100 Subject: [PATCH 004/135] Move out initial code of GoogleListingsAndAdsPlugin file --- .../GoogleListingsAndAdsPlugin.php | 102 ------------------ 1 file changed, 102 deletions(-) diff --git a/src/Infrastructure/GoogleListingsAndAdsPlugin.php b/src/Infrastructure/GoogleListingsAndAdsPlugin.php index 0c53b96f8f..315d230d67 100644 --- a/src/Infrastructure/GoogleListingsAndAdsPlugin.php +++ b/src/Infrastructure/GoogleListingsAndAdsPlugin.php @@ -32,12 +32,6 @@ final class GoogleListingsAndAdsPlugin implements Plugin { */ private $registered_services; - /** - * The client ID. - * @var string - */ - private $client_id; - /** * GoogleListingsAndAdsPlugin constructor. * @@ -121,12 +115,6 @@ function() { } ); - add_action( 'login_form_jetpack_json_api_authorization', array( $this, 'login_form_json_api_authorization' ) ); - - add_filter('jetpack_xmlrpc_test_connection_response', function (){ - return '1.40'; - }); - } /** @@ -155,94 +143,4 @@ protected function maybe_register_services(): void { $registered = true; } - - /** - * Handles the login action for Authorizing the JSON API - */ - public function login_form_json_api_authorization() { - add_action( 'wp_login', array( $this, 'store_json_api_authorization_token' ), 10, 2 ); - add_action( 'login_form', array( $this, 'preserve_action_in_login_form_for_json_api_authorization' ) ); - add_filter( 'site_url', array( $this, 'post_login_form_to_signed_url' ), 10, 3 ); - } - - /** - * If someone logs in to approve API access, store the Access Code in usermeta. - * - * @param string $user_login Unused. - * @param WP_User $user User logged in. - */ - public function store_json_api_authorization_token( $user_login, $user ) { - $data = json_decode( base64_decode( stripslashes( $_REQUEST['data'] ) ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode - $this->client_id = $data->client_id; - add_filter( 'login_redirect', array( $this, 'add_token_to_login_redirect_json_api_authorization' ), 10, 3 ); - add_filter( 'allowed_redirect_hosts', array( $this, 'allow_wpcom_public_api_domain' ) ); - $token = wp_generate_password( 32, false ); - update_user_meta( $user->ID, 'jetpack_json_api_' . $this->client_id, $token ); - } - - /** - * Make sure the POSTed request is handled by the same action. - */ - public function preserve_action_in_login_form_for_json_api_authorization() { - $http_host = isset( $_SERVER['HTTP_HOST'] ) ? wp_unslash( $_SERVER['HTTP_HOST'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- escaped with esc_url below. - $request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- escaped with esc_url below. - echo "\n"; - echo "\n"; - } - - /** - * Make sure the login form is POSTed to the signed URL so we can reverify the request. - * - * @param string $url Redirect URL. - * @param string $path Path. - * @param string $scheme URL Scheme. - */ - public function post_login_form_to_signed_url( $url, $path, $scheme ) { - if ( 'wp-login.php' !== $path || ( 'login_post' !== $scheme && 'login' !== $scheme ) ) { - return $url; - } - $query_string = isset( $_SERVER['QUERY_STRING'] ) ? wp_unslash( $_SERVER['QUERY_STRING'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized - $parsed_url = wp_parse_url( $url ); - $url = strtok( $url, '?' ); - $url = "$url?{$query_string}"; - if ( ! empty( $parsed_url['query'] ) ) { - $url .= "&{$parsed_url['query']}"; - } - - return $url; - } - - /** - * Add the Access Code details to the public-api.wordpress.com redirect. - * - * @param string $redirect_to URL. - * @param string $original_redirect_to URL. - * @param WP_User $user WP_User for the redirect. - * - * @return string - */ - public function add_token_to_login_redirect_json_api_authorization( $redirect_to, $original_redirect_to, $user ) { - return add_query_arg( - urlencode_deep( - array( - 'jetpack-code' => get_user_meta( $user->ID, 'jetpack_json_api_' . $this->client_id, true ), - 'jetpack-user-id' => (int) $user->ID, - 'jetpack-state' => '', - ) - ), - $redirect_to - ); - } - - /** - * Add public-api.wordpress.com to the safe redirect allowed list - only added when someone allows API access. - * - * To be used with a filter of allowed domains for a redirect. - * - * @param array $domains Allowed WP.com Environments. - */ - public function allow_wpcom_public_api_domain( $domains ) { - $domains[] = 'public-api.wordpress.com'; - return $domains; - } } From 1f7ca4ccc94576086966ef537a57193cf0c9a171 Mon Sep 17 00:00:00 2001 From: Jorge M Date: Tue, 7 Nov 2023 10:45:17 +0100 Subject: [PATCH 005/135] Added links to the Jetpack functions and remove duplicated PHPDoc --- src/Integration/JetpackWPCOM.php | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/Integration/JetpackWPCOM.php b/src/Integration/JetpackWPCOM.php index e112d82233..b2a7677201 100644 --- a/src/Integration/JetpackWPCOM.php +++ b/src/Integration/JetpackWPCOM.php @@ -20,6 +20,10 @@ * Initializes the Jetpack function required to connect the WPCOM App. * This class can be deleted when the jetpack-connection package includes these functions. * + * The majority of these class methods have been copied from the Jetpack class. + * + * @see https://github.com/Automattic/jetpack/blob/trunk/projects/plugins/jetpack/class.jetpack.php + * * @package Automattic\WooCommerce\GoogleListingsAndAds\Integration */ class JetpackWPCOM implements Service, Registerable, Conditional { @@ -64,6 +68,8 @@ public static function is_needed(): bool { /** * Handles the login action for Authorizing the JSON API + * + * @see https://github.com/Automattic/jetpack/blob/6066d7181f78bdec7c355d8b2152733f4691e8a9/projects/plugins/jetpack/class.jetpack.php#L5301 */ public function login_form_json_api_authorization() { $this->verify_json_api_authorization_request(); @@ -78,12 +84,8 @@ public function login_form_json_api_authorization() { * * @param string $user_login Unused. * @param WP_User $user User logged in. - */ - /** - * If someone logs in to approve API access, store the Access Code in usermeta. * - * @param string $user_login Unused. - * @param WP_User $user User logged in. + * @see https://github.com/Automattic/jetpack/blob/6066d7181f78bdec7c355d8b2152733f4691e8a9/projects/plugins/jetpack/class.jetpack.php#L5349 */ public function store_json_api_authorization_token( $user_login, $user ) { add_filter( 'login_redirect', [ $this, 'add_token_to_login_redirect_json_api_authorization' ], 10, 3 ); @@ -94,6 +96,8 @@ public function store_json_api_authorization_token( $user_login, $user ) { /** * Make sure the POSTed request is handled by the same action. + * + * @see https://github.com/Automattic/jetpack/blob/6066d7181f78bdec7c355d8b2152733f4691e8a9/projects/plugins/jetpack/class.jetpack.php#L5336 */ public function preserve_action_in_login_form_for_json_api_authorization() { $http_host = isset( $_SERVER['HTTP_HOST'] ) ? wp_unslash( $_SERVER['HTTP_HOST'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- escaped with esc_url below. @@ -108,6 +112,8 @@ public function preserve_action_in_login_form_for_json_api_authorization() { * @param string $url Redirect URL. * @param string $path Path. * @param string $scheme URL Scheme. + * + * @see https://github.com/Automattic/jetpack/blob/trunk/projects/plugins/jetpack/class.jetpack.php#L5318 */ public function post_login_form_to_signed_url( $url, $path, $scheme ) { if ( 'wp-login.php' !== $path || ( 'login_post' !== $scheme && 'login' !== $scheme ) ) { @@ -132,6 +138,8 @@ public function post_login_form_to_signed_url( $url, $path, $scheme ) { * @param WP_User $user WP_User for the redirect. * * @return string + * + * @see https://github.com/Automattic/jetpack/blob/6066d7181f78bdec7c355d8b2152733f4691e8a9/projects/plugins/jetpack/class.jetpack.php#L5401 */ public function add_token_to_login_redirect_json_api_authorization( $redirect_to, $original_redirect_to, $user ) { return add_query_arg( @@ -148,10 +156,11 @@ public function add_token_to_login_redirect_json_api_authorization( $redirect_to /** * Add public-api.wordpress.com to the safe redirect allowed list - only added when someone allows API access. - * * To be used with a filter of allowed domains for a redirect. * * @param array $domains Allowed WP.com Environments. + * + * @see https://github.com/Automattic/jetpack/blob/6066d7181f78bdec7c355d8b2152733f4691e8a9/projects/plugins/jetpack/class.jetpack.php#L5363 */ public function allow_wpcom_public_api_domain( $domains ) { $domains[] = 'public-api.wordpress.com'; @@ -164,6 +173,8 @@ public function allow_wpcom_public_api_domain( $domains ) { * @param string $redirect_url Redirect URL. * * @return bool If redirect has been encoded. + * + * @see https://github.com/Automattic/jetpack/blob/6066d7181f78bdec7c355d8b2152733f4691e8a9/projects/plugins/jetpack/class.jetpack.php#L5375 */ public static function is_redirect_encoded( $redirect_url ) { return preg_match( '/https?%3A%2F%2F/i', $redirect_url ) > 0; @@ -173,6 +184,8 @@ public static function is_redirect_encoded( $redirect_url ) { * HTML for the JSON API authorization notice. * * @return string + * + * @see https://github.com/Automattic/jetpack/blob/6066d7181f78bdec7c355d8b2152733f4691e8a9/projects/plugins/jetpack/class.jetpack.php#L5603 */ public function login_message_json_api_authorization() { return '

' . sprintf( @@ -185,10 +198,9 @@ public function login_message_json_api_authorization() { /** * Verifies the request by checking the signature * - * @since 4.6.0 Method was updated to use `$_REQUEST` instead of `$_GET` and `$_POST`. Method also updated to allow - * passing in an `$environment` argument that overrides `$_REQUEST`. This was useful for integrating with SSO. - * * @param null|array $environment Value to override $_REQUEST. + * + * @see https://github.com/Automattic/jetpack/blob/trunk/projects/plugins/jetpack/class.jetpack.php#L5422 */ public function verify_json_api_authorization_request( $environment = null ) { $environment = $environment === null @@ -207,8 +219,6 @@ public function verify_json_api_authorization_request( $environment = null ) { if ( self::is_redirect_encoded( esc_url_raw( wp_unslash( $_GET['redirect_to'] ) ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotValidated -- no site changes, we're erroring out. /** * Jetpack authorisation request Error. - * - * @since 7.5.0 */ do_action( 'jetpack_verify_api_authorization_request_error_double_encode' ); $die_error = sprintf( From b4130fe5ca7e38cd6fad629ae262beff8e5eca12 Mon Sep 17 00:00:00 2001 From: Jorge M Date: Thu, 9 Nov 2023 21:43:34 +0100 Subject: [PATCH 006/135] Filter results for WC Proxy --- src/Integration/WooCoommerceProxy.php | 218 ++++++++++++++++++ .../IntegrationServiceProvider.php | 2 + 2 files changed, 220 insertions(+) create mode 100644 src/Integration/WooCoommerceProxy.php diff --git a/src/Integration/WooCoommerceProxy.php b/src/Integration/WooCoommerceProxy.php new file mode 100644 index 0000000000..835ff75f3d --- /dev/null +++ b/src/Integration/WooCoommerceProxy.php @@ -0,0 +1,218 @@ + [ + 'meta_query' => [ + [ + 'key' => '_wc_gla_visibility', + 'value' => 'sync-and-show', + 'compare' => '=', + ], + ], + ], + 'shop_coupon' => [ + 'meta_query' => [ + [ + 'key' => '_wc_gla_visibility', + 'value' => 'sync-and-show', + 'compare' => '=', + ], + [ + 'key' => 'customer_email', + 'compare' => 'NOT EXISTS', + ], + ], + ], + 'product_variation' => [ + 'meta_query' => null, + ], + ]; + + /** + * Check if the request is a API request. + * + * @return bool Whether the class is needed. + */ + public static function is_needed(): bool { + // phpcs:ignore WordPress.Security.NonceVerification.Recommended + return self::is_request_to_rest_api() && isset( $_GET['gla_syncable'] ); + } + + /** + * Check if is request to the WC REST API. + * + * This function is based on the WooCommerce function is_rest_api_request() but also checks for rest_route=/wc/ regardless the permalink settings. + * + * @see https://github.com/woocommerce/woocommerce/blob/bae3a34501047bfdff4d79c240396f38cdcd1f25/plugins/woocommerce/includes/class-wc-rest-authentication.php#L62 + * @see https://github.com/woocommerce/woocommerce/issues/41191 + * + * @return bool Whether the request is to the WC REST API. + */ + public static function is_request_to_rest_api(): bool { + if ( empty( $_SERVER['REQUEST_URI'] ) ) { + return false; + } + + $rest_prefix = trailingslashit( rest_get_url_prefix() ); + $request_uri = esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ); + + // Check if the request is to the WC API endpoints. + return ( false !== strpos( $request_uri, $rest_prefix . 'wc/' ) ) || ( false !== strpos( $request_uri, 'rest_route=/wc/' ) ); + } + + /** + * Register all filters. + */ + public function register(): void { + add_filter( + 'woocommerce_rest_query_vars', + function( $valid_vars ) { + $valid_vars[] = 'gla_syncable'; + return $valid_vars; + } + ); + + foreach ( array_keys( self::$post_types_to_be_filter ) as $object_type ) { + $this->register_object_types_filter( $object_type ); + } + + } + + /** + * Register the filters for a specific object type. + * + * @param string $object_type The object type. + */ + protected function register_object_types_filter( string $object_type ): void { + add_filter( 'woocommerce_rest_prepare_' . $object_type . '_object', [ $this, 'check_item_is_syncable' ], 9, 3 ); + + add_filter( + 'woocommerce_rest_prepare_' . $object_type . '_object', + [ $this, 'filter_metadata' ], + 10, + 3 + ); + + add_filter( + 'woocommerce_rest_' . $object_type . '_object_query', + [ $this, 'filter_by_metaquery' ], + 10, + 2 + ); + + } + + /** + * Check if a single item is syncable. + * + * @param WP_REST_Response $response The response object. + * @param mixed $object The object. + * @param WP_REST_Request $request The request object. + * + * @return WP_REST_Response The response object updated. + */ + public function check_item_is_syncable( $response, $object, $request ): WP_REST_Response { + $route = $request->get_route(); + $pattern = '/(?P[\w]+)\/(?P[\d]+)/'; + $protected_resources = [ + 'products', + 'coupons', + ]; + preg_match( $pattern, $route, $matches ); + + if ( ! isset( $matches['id'] ) || ! isset( $matches['resource'] ) || ! in_array( $matches['resource'], $protected_resources, true ) ) { + return $response; + } + + $meta_data = $response->get_data()['meta_data'] ?? []; + + foreach ( $meta_data as $meta ) { + if ( $meta->key === '_wc_gla_visibility' && $meta->value === 'sync-and-show' ) { + return $response; + } + } + + return new WP_REST_Response( + [ + 'code' => 'gla_rest_item_no_syncable', + 'message' => 'Item not syncable', + 'data' => [ + 'status' => '403', + ], + ], + 403 + ); + + } + + /** + * Query items with specific args for example where _wc_gla_visibility is set to sync-and-show. + * + * @param array $args The query args. + * + * @return array The query args updated. + * */ + public function filter_by_metaquery( array $args ): array { + $post_type = $args['post_type']; + $post_type_filters = self::$post_types_to_be_filter[ $post_type ]; + + if ( ! isset( $post_type_filters['meta_query'] ) || ! is_array( $post_type_filters['meta_query'] ) ) { + return $args; + } + + $args['meta_query'] = [ ...$args['meta_query'] ?? [], ...$post_type_filters['meta_query'] ]; + + return $args; + } + + /** + * Filter the metadata of an object. + * + * @param WP_REST_Response $response The response object. + * + * @return WP_REST_Response The response object updated. + */ + public function filter_metadata( WP_REST_Response $response ): WP_REST_Response { + $data = $response->get_data(); + + if ( ! isset( $data['meta_data'] ) ) { + return $response; + } + + foreach ( $data['meta_data'] as $key => $meta ) { + if ( str_starts_with( $meta->key, '_' ) && ! str_starts_with( $meta->key, '_wc_gla' ) ) { + unset( $data['meta_data'][ $key ] ); + } + } + + $data['meta_data'] = array_values( $data['meta_data'] ); + $response->set_data( $data ); + + return $response; + } + +} diff --git a/src/Internal/DependencyManagement/IntegrationServiceProvider.php b/src/Internal/DependencyManagement/IntegrationServiceProvider.php index 710e9fc5b7..2c3c26bcea 100644 --- a/src/Internal/DependencyManagement/IntegrationServiceProvider.php +++ b/src/Internal/DependencyManagement/IntegrationServiceProvider.php @@ -10,6 +10,7 @@ use Automattic\WooCommerce\GoogleListingsAndAds\Integration\WooCommerceBrands; use Automattic\WooCommerce\GoogleListingsAndAds\Integration\WooCommercePreOrders; use Automattic\WooCommerce\GoogleListingsAndAds\Integration\WooCommerceProductBundles; +use Automattic\WooCommerce\GoogleListingsAndAds\Integration\WooCoommerceProxy; use Automattic\WooCommerce\GoogleListingsAndAds\Integration\YoastWooCommerceSeo; use Automattic\WooCommerce\GoogleListingsAndAds\Integration\JetpackWPCOM; use Automattic\WooCommerce\GoogleListingsAndAds\Product\Attributes\AttributeManager; @@ -47,6 +48,7 @@ public function register(): void { $this->share_with_tags( WooCommerceProductBundles::class, AttributeManager::class ); $this->share_with_tags( WooCommercePreOrders::class, ProductHelper::class ); $this->conditionally_share_with_tags( JetpackWPCOM::class ); + $this->conditionally_share_with_tags( WooCoommerceProxy::class ); $this->share_with_tags( IntegrationInitializer::class, From ebe97982ab2c9e46e8b4cce1057ffb0b4ea8c0ce Mon Sep 17 00:00:00 2001 From: Jorge M Date: Thu, 9 Nov 2023 21:43:57 +0100 Subject: [PATCH 007/135] WIP tests --- tests/Unit/Proxy/WCProxyTest.php | 58 ++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 tests/Unit/Proxy/WCProxyTest.php diff --git a/tests/Unit/Proxy/WCProxyTest.php b/tests/Unit/Proxy/WCProxyTest.php new file mode 100644 index 0000000000..e9147a8e12 --- /dev/null +++ b/tests/Unit/Proxy/WCProxyTest.php @@ -0,0 +1,58 @@ + 'private', + 'public_meta' => 'public', + '_wc_gla_visibility' => 'sync-and-show', + ]; + + $coupon_1 = CouponHelper::create_coupon( 'dummycoupon-1', 'publish', $meta ); + $coupon_2 = CouponHelper::create_coupon( 'dummycoupon-2', 'publish', $meta ); + + delete_post_meta( $coupon_1->get_id(), 'customer_email' ); + delete_post_meta( $coupon_2->get_id(), 'customer_email' ); + + $response = $this->do_request( '/wc/v3/coupons', 'GET', ['gla_syncable' => 1] ); + + foreach ( $response->get_data() as $coupon ) { + var_dump( $coupon['meta_data'] ); + //$this->assertArrayNotHasKey( '_private_meta', $coupon ); + //$this->assertArrayHasKey( 'public_meta', $coupon ); + } + + //$this->assertEquals( self::TEST_BILLING_STATUS_DATA, $response->get_data() ); + $this->assertEquals( 200, $response->get_status() ); + } + +} From dc1fcb640e4e33c16154d858f3e10ddb562c6ed5 Mon Sep 17 00:00:00 2001 From: Jorge M Date: Fri, 10 Nov 2023 01:15:22 +0100 Subject: [PATCH 008/135] Rename file --- .../{WooCoommerceProxy.php => WPCOMProxy.php} | 77 +++++++++---------- .../IntegrationServiceProvider.php | 4 +- 2 files changed, 38 insertions(+), 43 deletions(-) rename src/Integration/{WooCoommerceProxy.php => WPCOMProxy.php} (68%) diff --git a/src/Integration/WooCoommerceProxy.php b/src/Integration/WPCOMProxy.php similarity index 68% rename from src/Integration/WooCoommerceProxy.php rename to src/Integration/WPCOMProxy.php index 835ff75f3d..3380e98d2c 100644 --- a/src/Integration/WooCoommerceProxy.php +++ b/src/Integration/WPCOMProxy.php @@ -5,19 +5,19 @@ use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Registerable; use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service; -use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Conditional; use WP_REST_Response; +use WP_REST_Request; defined( 'ABSPATH' ) || exit; /** - * Class WooCoommerceProxy + * Class WPCOMProxy * - * Initializes the hooks to filter the data sent to the proxy depending on the query parameter gla_syncable. + * Initializes the hooks to filter the data sent to the WPCOM proxy depending on the query parameter gla_syncable. * * @package Automattic\WooCommerce\GoogleListingsAndAds\Integration */ -class WooCoommerceProxy implements Service, Registerable, Conditional { +class WPCOMProxy implements Service, Registerable { /** * The Post types to be filtered. @@ -52,42 +52,11 @@ class WooCoommerceProxy implements Service, Registerable, Conditional { ], ]; - /** - * Check if the request is a API request. - * - * @return bool Whether the class is needed. - */ - public static function is_needed(): bool { - // phpcs:ignore WordPress.Security.NonceVerification.Recommended - return self::is_request_to_rest_api() && isset( $_GET['gla_syncable'] ); - } - - /** - * Check if is request to the WC REST API. - * - * This function is based on the WooCommerce function is_rest_api_request() but also checks for rest_route=/wc/ regardless the permalink settings. - * - * @see https://github.com/woocommerce/woocommerce/blob/bae3a34501047bfdff4d79c240396f38cdcd1f25/plugins/woocommerce/includes/class-wc-rest-authentication.php#L62 - * @see https://github.com/woocommerce/woocommerce/issues/41191 - * - * @return bool Whether the request is to the WC REST API. - */ - public static function is_request_to_rest_api(): bool { - if ( empty( $_SERVER['REQUEST_URI'] ) ) { - return false; - } - - $rest_prefix = trailingslashit( rest_get_url_prefix() ); - $request_uri = esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ); - - // Check if the request is to the WC API endpoints. - return ( false !== strpos( $request_uri, $rest_prefix . 'wc/' ) ) || ( false !== strpos( $request_uri, 'rest_route=/wc/' ) ); - } - /** * Register all filters. */ public function register(): void { + // Allow to filter by gla_syncable. add_filter( 'woocommerce_rest_query_vars', function( $valid_vars ) { @@ -126,6 +95,17 @@ protected function register_object_types_filter( string $object_type ): void { } + /** + * Whether the data should be filtered. + * + * @param WP_REST_Request $request The request object. + * + * @return bool + */ + protected function should_filter_data( WP_REST_Request $request ): bool { + return $request->get_param( 'gla_syncable' ) !== null; + } + /** * Check if a single item is syncable. * @@ -135,9 +115,13 @@ protected function register_object_types_filter( string $object_type ): void { * * @return WP_REST_Response The response object updated. */ - public function check_item_is_syncable( $response, $object, $request ): WP_REST_Response { + public function check_item_is_syncable( $response, $object, WP_REST_Request $request ): WP_REST_Response { + if ( ! $this->should_filter_data( $request ) ) { + return $response; + } + $route = $request->get_route(); - $pattern = '/(?P[\w]+)\/(?P[\d]+)/'; + $pattern = '/(?P[\w]+)\/(?P[\d]+$)/'; $protected_resources = [ 'products', 'coupons', @@ -172,11 +156,16 @@ public function check_item_is_syncable( $response, $object, $request ): WP_REST_ /** * Query items with specific args for example where _wc_gla_visibility is set to sync-and-show. * - * @param array $args The query args. + * @param array $args The query args. + * @param WP_REST_Request $request The request object. * * @return array The query args updated. * */ - public function filter_by_metaquery( array $args ): array { + public function filter_by_metaquery( array $args, WP_REST_Request $request ): array { + if ( ! $this->should_filter_data( $request ) ) { + return $args; + } + $post_type = $args['post_type']; $post_type_filters = self::$post_types_to_be_filter[ $post_type ]; @@ -193,10 +182,16 @@ public function filter_by_metaquery( array $args ): array { * Filter the metadata of an object. * * @param WP_REST_Response $response The response object. + * @param mixed $object The object. + * @param WP_REST_Request $request The request object. * * @return WP_REST_Response The response object updated. */ - public function filter_metadata( WP_REST_Response $response ): WP_REST_Response { + public function filter_metadata( WP_REST_Response $response, $object, WP_REST_Request $request ): WP_REST_Response { + if ( ! $this->should_filter_data( $request ) ) { + return $response; + } + $data = $response->get_data(); if ( ! isset( $data['meta_data'] ) ) { diff --git a/src/Internal/DependencyManagement/IntegrationServiceProvider.php b/src/Internal/DependencyManagement/IntegrationServiceProvider.php index 2c3c26bcea..d38296beb2 100644 --- a/src/Internal/DependencyManagement/IntegrationServiceProvider.php +++ b/src/Internal/DependencyManagement/IntegrationServiceProvider.php @@ -10,7 +10,7 @@ use Automattic\WooCommerce\GoogleListingsAndAds\Integration\WooCommerceBrands; use Automattic\WooCommerce\GoogleListingsAndAds\Integration\WooCommercePreOrders; use Automattic\WooCommerce\GoogleListingsAndAds\Integration\WooCommerceProductBundles; -use Automattic\WooCommerce\GoogleListingsAndAds\Integration\WooCoommerceProxy; +use Automattic\WooCommerce\GoogleListingsAndAds\Integration\WPCOMProxy; use Automattic\WooCommerce\GoogleListingsAndAds\Integration\YoastWooCommerceSeo; use Automattic\WooCommerce\GoogleListingsAndAds\Integration\JetpackWPCOM; use Automattic\WooCommerce\GoogleListingsAndAds\Product\Attributes\AttributeManager; @@ -48,7 +48,7 @@ public function register(): void { $this->share_with_tags( WooCommerceProductBundles::class, AttributeManager::class ); $this->share_with_tags( WooCommercePreOrders::class, ProductHelper::class ); $this->conditionally_share_with_tags( JetpackWPCOM::class ); - $this->conditionally_share_with_tags( WooCoommerceProxy::class ); + $this->share_with_tags( WPCOMProxy::class ); $this->share_with_tags( IntegrationInitializer::class, From e77bdbfc9ed46fd43ff88a3b0f056ca355313e11 Mon Sep 17 00:00:00 2001 From: Jorge M Date: Fri, 10 Nov 2023 01:15:38 +0100 Subject: [PATCH 009/135] Add tests --- tests/Unit/Integration/WPCOMProxyTest.php | 358 ++++++++++++++++++++++ tests/Unit/Proxy/WCProxyTest.php | 58 ---- 2 files changed, 358 insertions(+), 58 deletions(-) create mode 100644 tests/Unit/Integration/WPCOMProxyTest.php delete mode 100644 tests/Unit/Proxy/WCProxyTest.php diff --git a/tests/Unit/Integration/WPCOMProxyTest.php b/tests/Unit/Integration/WPCOMProxyTest.php new file mode 100644 index 0000000000..ad2f6f42e7 --- /dev/null +++ b/tests/Unit/Integration/WPCOMProxyTest.php @@ -0,0 +1,358 @@ +key ] = $meta->value; + } + + return $new_metadata; + } + + /** + * Return the metadata to be used in the tests. + * + * @param string|null $visibility The _wc_gla_visibility metadata. + * + * @return array + */ + protected function get_test_metadata( $visibility = 'sync-and-show' ): array { + $args = [ + '_private_meta' => 'private', + 'public_meta' => 'public', + ]; + + if ( $visibility ) { + $args['_wc_gla_visibility'] = $visibility; + } + return $args; + } + + /** + * Add metadata to a item. + * + * @param int $id The item id. + * @param array $meta The metadata to be added. + */ + protected function add_metadata( int $id, array $meta ) { + // Update meta. + foreach ( $meta as $key => $value ) { + update_post_meta( $id, $key, $value ); + } + } + + /** + * Maps the response with the item id. + * + * @param WP_REST_Response $response The response. + * + * @return array + */ + protected function maps_the_response_with_the_item_id( WP_REST_Response $response ): array { + return array_reduce( + $response->get_data(), + function( $c, $i ) { + $c[ $i['id'] ] = $i; + return $c; + }, + [] + ); + } + + public function test_get_products() { + $product_1 = ProductHelper::create_simple_product(); + $product_2 = ProductHelper::create_simple_product(); + + $this->add_metadata( $product_1->get_id(), $this->get_test_metadata() ); + $this->add_metadata( $product_2->get_id(), $this->get_test_metadata( 'dont-sync-and-show' ) ); + + $response = $this->do_request( '/wc/v3/products', 'GET', [ 'gla_syncable' => 1 ] ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertCount( 1, $response->get_data() ); + + $expected_metadata = [ + 'public_meta' => 'public', + '_wc_gla_visibility' => 'sync-and-show', + ]; + + $this->assertEquals( $product_1->get_id(), $response->get_data()[0]['id'] ); + $this->assertEquals( $expected_metadata, $this->format_metadata( $response->get_data()[0]['meta_data'] ) ); + } + + public function test_get_products_without_gla_visibility_metadata() { + $product_1 = ProductHelper::create_simple_product(); + $product_2 = ProductHelper::create_simple_product(); + + $this->add_metadata( $product_1->get_id(), $this->get_test_metadata( null ) ); + $this->add_metadata( $product_2->get_id(), $this->get_test_metadata() ); + + $response = $this->do_request( '/wc/v3/products', 'GET', [ 'gla_syncable' => 1 ] ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertCount( 1, $response->get_data() ); + + $expected_metadata = [ + 'public_meta' => 'public', + '_wc_gla_visibility' => 'sync-and-show', + ]; + + $this->assertEquals( $product_2->get_id(), $response->get_data()[0]['id'] ); + $this->assertEquals( $expected_metadata, $this->format_metadata( $response->get_data()[0]['meta_data'] ) ); + } + + public function test_get_product_without_gla_visibility_metadata() { + // If _wc_gla_visibility is not set it should not be returned. + $product = ProductHelper::create_simple_product(); + $this->add_metadata( $product->get_id(), $this->get_test_metadata( null ) ); + + delete_post_meta( $product->get_id(), 'customer_email' ); + + $response = $this->do_request( '/wc/v3/products/' . $product->get_id(), 'GET', [ 'gla_syncable' => 1 ] ); + + $this->assertEquals( 403, $response->get_status() ); + $this->assertEquals( 'gla_rest_item_no_syncable', $response->get_data()['code'] ); + $this->assertEquals( 'Item not syncable', $response->get_data()['message'] ); + } + + public function test_get_product_with_gla_visibility_metadata() { + $product = ProductHelper::create_simple_product(); + $this->add_metadata( $product->get_id(), $this->get_test_metadata() ); + + $response = $this->do_request( '/wc/v3/products/' . $product->get_id(), 'GET', [ 'gla_syncable' => 1 ] ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertEquals( $product->get_id(), $response->get_data()['id'] ); + } + + + public function test_get_product_without_gla_syncable_param() { + $product = ProductHelper::create_simple_product(); + $this->add_metadata( $product->get_id(), $this->get_test_metadata( null ) ); + + $response = $this->do_request( '/wc/v3/products/' . $product->get_id(), 'GET' ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertEquals( $product->get_id(), $response->get_data()['id'] ); + } + + public function test_get_products_without_gla_syncable_param() { + $product_1 = ProductHelper::create_simple_product(); + $product_2 = ProductHelper::create_simple_product(); + $this->add_metadata( $product_1->get_id(), $this->get_test_metadata() ); + $this->add_metadata( $product_2->get_id(), $this->get_test_metadata( 'dont-sync-and-show' ) ); + + $response = $this->do_request( '/wc/v3/products', 'GET' ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertCount( 2, $response->get_data() ); + + $response_mapped = $this->maps_the_response_with_the_item_id( $response ); + + $this->assertArrayHasKey( $product_1->get_id(), $response_mapped ); + $this->assertArrayHasKey( $product_2->get_id(), $response_mapped ); + + $this->assertEquals( $this->get_test_metadata(), $this->format_metadata( $response_mapped[ $product_1->get_id() ]['meta_data'] ) ); + $this->assertEquals( $this->get_test_metadata( 'dont-sync-and-show' ), $this->format_metadata( $response_mapped[ $product_2->get_id() ]['meta_data'] ) ); + } + + public function test_get_variations() { + $product = ProductHelper::create_variation_product(); + $variations = $product->get_available_variations(); + + foreach ( $variations as $variation ) { + // Variations don't have the _wc_gla_visibility metadata, the parent product has it. For now we can only filter the private metadata. + $this->add_metadata( $variation['variation_id'], $this->get_test_metadata( null ) ); + } + + $response = $this->do_request( '/wc/v3/products/' . $product->get_id() . '/variations', 'GET', [ 'gla_syncable' => 1 ] ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertCount( count( $variations ), $response->get_data() ); + + $response_mapped = $this->maps_the_response_with_the_item_id( $response ); + + $expected_metadata = [ + 'public_meta' => 'public', + ]; + + foreach ( $variations as $variation ) { + $this->assertArrayHasKey( $variation['variation_id'], $response_mapped ); + $this->assertEquals( $expected_metadata, $this->format_metadata( $response_mapped[ $variation['variation_id'] ]['meta_data'] ) ); + } + } + + public function test_get_variations_without_gla_syncable_param() { + $product = ProductHelper::create_variation_product(); + $variations = $product->get_available_variations(); + + foreach ( $variations as $variation ) { + // Variations don't have the _wc_gla_visibility metadata, the parent product has it. For now we can only filter the private metadata. + $this->add_metadata( $variation['variation_id'], $this->get_test_metadata( null ) ); + } + + $response = $this->do_request( '/wc/v3/products/' . $product->get_id() . '/variations' ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertCount( count( $variations ), $response->get_data() ); + + $response_mapped = $this->maps_the_response_with_the_item_id( $response ); + + $expected_metadata = [ + 'public_meta' => 'public', + '_private_meta' => 'private', + ]; + + foreach ( $variations as $variation ) { + $this->assertArrayHasKey( $variation['variation_id'], $response_mapped ); + $this->assertEquals( $expected_metadata, $this->format_metadata( $response_mapped[ $variation['variation_id'] ]['meta_data'] ) ); + } + } + + public function test_get_coupons() { + $coupon_1 = CouponHelper::create_coupon( 'dummycoupon-1', 'publish', $this->get_test_metadata() ); + $coupon_2 = CouponHelper::create_coupon( 'dummycoupon-2', 'publish', $this->get_test_metadata( 'dont-sync-and-show' ) ); + + delete_post_meta( $coupon_1->get_id(), 'customer_email' ); + delete_post_meta( $coupon_2->get_id(), 'customer_email' ); + + $response = $this->do_request( '/wc/v3/coupons', 'GET', [ 'gla_syncable' => 1 ] ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertCount( 1, $response->get_data() ); + + $expected_metadata = [ + 'public_meta' => 'public', + '_wc_gla_visibility' => 'sync-and-show', + ]; + + $this->assertEquals( $coupon_1->get_id(), $response->get_data()[0]['id'] ); + $this->assertEquals( $expected_metadata, $this->format_metadata( $response->get_data()[0]['meta_data'] ) ); + + } + + public function test_get_coupons_with_customer_email_and_syncable() { + // Even that this coupon has the _wc_gla_visibility set to sync-and-show, it should not be returned because it has a customer_email set. + CouponHelper::create_coupon( 'dummycoupon-1', 'publish', array_merge( $this->get_test_metadata(), [ 'customer_email' => 'john@smith.com' ] ) ); + $coupon = CouponHelper::create_coupon( 'dummycoupon-2', 'publish', $this->get_test_metadata() ); + + delete_post_meta( $coupon->get_id(), 'customer_email' ); + + $response = $this->do_request( '/wc/v3/coupons', 'GET', [ 'gla_syncable' => 1 ] ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertCount( 1, $response->get_data() ); + + $expected_metadata = [ + 'public_meta' => 'public', + '_wc_gla_visibility' => 'sync-and-show', + ]; + + $this->assertEquals( $coupon->get_id(), $response->get_data()[0]['id'] ); + $this->assertEquals( $expected_metadata, $this->format_metadata( $response->get_data()[0]['meta_data'] ) ); + } + + public function test_get_coupons_without_gla_visibility_metadata() { + // If _wc_gla_visibility is not set it should not be returned. + CouponHelper::create_coupon( 'dummycoupon-1', 'publish', $this->get_test_metadata( null ) ); + $coupon = CouponHelper::create_coupon( 'dummycoupon-2', 'publish', $this->get_test_metadata() ); + + delete_post_meta( $coupon->get_id(), 'customer_email' ); + + $response = $this->do_request( '/wc/v3/coupons', 'GET', [ 'gla_syncable' => 1 ] ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertCount( 1, $response->get_data() ); + + $expected_metadata = [ + 'public_meta' => 'public', + '_wc_gla_visibility' => 'sync-and-show', + ]; + + $this->assertEquals( $coupon->get_id(), $response->get_data()[0]['id'] ); + $this->assertEquals( $expected_metadata, $this->format_metadata( $response->get_data()[0]['meta_data'] ) ); + } + + public function test_get_coupon_without_gla_visibility_metadata() { + // If _wc_gla_visibility is not set it should not be returned. + $coupon = CouponHelper::create_coupon( 'dummycoupon-1', 'publish', $this->get_test_metadata( null ) ); + + delete_post_meta( $coupon->get_id(), 'customer_email' ); + + $response = $this->do_request( '/wc/v3/coupons/' . $coupon->get_id(), 'GET', [ 'gla_syncable' => 1 ] ); + + $this->assertEquals( 403, $response->get_status() ); + $this->assertEquals( 'gla_rest_item_no_syncable', $response->get_data()['code'] ); + $this->assertEquals( 'Item not syncable', $response->get_data()['message'] ); + } + + public function test_get_coupon_with_gla_visibility_metadata() { + $coupon = CouponHelper::create_coupon( 'dummycoupon-1', 'publish', $this->get_test_metadata() ); + + delete_post_meta( $coupon->get_id(), 'customer_email' ); + + $response = $this->do_request( '/wc/v3/coupons/' . $coupon->get_id(), 'GET', [ 'gla_syncable' => 1 ] ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertEquals( $coupon->get_id(), $response->get_data()['id'] ); + } + + public function test_get_coupon_without_gla_syncable_param() { + $coupon = CouponHelper::create_coupon( 'dummycoupon-1', 'publish', $this->get_test_metadata( null ) ); + + $response = $this->do_request( '/wc/v3/coupons/' . $coupon->get_id(), 'GET' ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertEquals( $coupon->get_id(), $response->get_data()['id'] ); + } + + public function test_get_coupons_without_gla_syncable_param() { + $coupon_1 = CouponHelper::create_coupon( 'dummycoupon-1', 'publish', $this->get_test_metadata() ); + $coupon_2 = CouponHelper::create_coupon( 'dummycoupon-2', 'publish', $this->get_test_metadata( 'dont-sync-and-show' ) ); + + $response = $this->do_request( '/wc/v3/coupons', 'GET' ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertCount( 2, $response->get_data() ); + + $response_mapped = $this->maps_the_response_with_the_item_id( $response ); + + $this->assertArrayHasKey( $coupon_1->get_id(), $response_mapped ); + $this->assertArrayHasKey( $coupon_2->get_id(), $response_mapped ); + + $this->assertEquals( $this->get_test_metadata(), $this->format_metadata( $response_mapped[ $coupon_1->get_id() ]['meta_data'] ) ); + $this->assertEquals( $this->get_test_metadata( 'dont-sync-and-show' ), $this->format_metadata( $response_mapped[ $coupon_2->get_id() ]['meta_data'] ) ); + + } + +} diff --git a/tests/Unit/Proxy/WCProxyTest.php b/tests/Unit/Proxy/WCProxyTest.php deleted file mode 100644 index e9147a8e12..0000000000 --- a/tests/Unit/Proxy/WCProxyTest.php +++ /dev/null @@ -1,58 +0,0 @@ - 'private', - 'public_meta' => 'public', - '_wc_gla_visibility' => 'sync-and-show', - ]; - - $coupon_1 = CouponHelper::create_coupon( 'dummycoupon-1', 'publish', $meta ); - $coupon_2 = CouponHelper::create_coupon( 'dummycoupon-2', 'publish', $meta ); - - delete_post_meta( $coupon_1->get_id(), 'customer_email' ); - delete_post_meta( $coupon_2->get_id(), 'customer_email' ); - - $response = $this->do_request( '/wc/v3/coupons', 'GET', ['gla_syncable' => 1] ); - - foreach ( $response->get_data() as $coupon ) { - var_dump( $coupon['meta_data'] ); - //$this->assertArrayNotHasKey( '_private_meta', $coupon ); - //$this->assertArrayHasKey( 'public_meta', $coupon ); - } - - //$this->assertEquals( self::TEST_BILLING_STATUS_DATA, $response->get_data() ); - $this->assertEquals( 200, $response->get_status() ); - } - -} From 61a4c5b0095387adde688a8f3478f5147c655cb9 Mon Sep 17 00:00:00 2001 From: Martyn Jones Date: Thu, 9 Nov 2023 19:50:38 +0000 Subject: [PATCH 010/135] Update phpunit polyfills to 1.1 for WP 6.4 --- composer.json | 4 +- composer.lock | 780 ++++++++++++++++++++++++-------------------------- 2 files changed, 380 insertions(+), 404 deletions(-) diff --git a/composer.json b/composer.json index 8e99acd290..e53b914e5f 100644 --- a/composer.json +++ b/composer.json @@ -25,8 +25,8 @@ "dealerdirect/phpcodesniffer-composer-installer": "^v0.7", "phpunit/phpunit": "^9.5", "wp-cli/i18n-command": "^2.2", - "wp-coding-standards/wpcs": "^2.3", - "yoast/phpunit-polyfills": "^1.0" + "wp-coding-standards/wpcs": "^3.0", + "yoast/phpunit-polyfills": "^1.1.0" }, "replace" : { "google/grpc-gcp": "*", diff --git a/composer.lock b/composer.lock index f888707051..6ac0469f4a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,25 +4,28 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e11445388ffb41fd143162a17acf77b8", + "content-hash": "44d590a9ed062f32ccca8e0708ef9350", "packages": [ { "name": "automattic/jetpack-a8c-mc-stats", - "version": "v1.4.13", + "version": "v1.4.22", "source": { "type": "git", "url": "https://github.com/Automattic/jetpack-a8c-mc-stats.git", - "reference": "64ee9a83861c6b2c8744e2ebc25157806f3548e0" + "reference": "d7fdf2fc7ae33d75e24e82d81269e33ec718446f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Automattic/jetpack-a8c-mc-stats/zipball/64ee9a83861c6b2c8744e2ebc25157806f3548e0", - "reference": "64ee9a83861c6b2c8744e2ebc25157806f3548e0", + "url": "https://api.github.com/repos/Automattic/jetpack-a8c-mc-stats/zipball/d7fdf2fc7ae33d75e24e82d81269e33ec718446f", + "reference": "d7fdf2fc7ae33d75e24e82d81269e33ec718446f", "shasum": "" }, "require-dev": { - "automattic/jetpack-changelogger": "^3.1", - "yoast/phpunit-polyfills": "1.0.3" + "automattic/jetpack-changelogger": "^3.3.9", + "yoast/phpunit-polyfills": "1.1.0" + }, + "suggest": { + "automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package." }, "type": "jetpack-library", "extra": { @@ -32,7 +35,7 @@ "link-template": "https://github.com/Automattic/jetpack-a8c-mc-stats/compare/v${old}...v${new}" }, "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-trunk": "1.4.x-dev" } }, "autoload": { @@ -46,28 +49,32 @@ ], "description": "Used to record internal usage stats for Automattic. Not visible to site owners.", "support": { - "source": "https://github.com/Automattic/jetpack-a8c-mc-stats/tree/v1.4.13" + "source": "https://github.com/Automattic/jetpack-a8c-mc-stats/tree/v1.4.22" }, - "time": "2022-04-26T14:33:27+00:00" + "time": "2023-09-19T18:18:33+00:00" }, { "name": "automattic/jetpack-admin-ui", - "version": "v0.2.7", + "version": "v0.2.24", "source": { "type": "git", "url": "https://github.com/Automattic/jetpack-admin-ui.git", - "reference": "56a60ee4d03ac2be62cb341e3df0f2fb5cc851f8" + "reference": "334858057237be51aa916352c7573fc4c06bbd6c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Automattic/jetpack-admin-ui/zipball/56a60ee4d03ac2be62cb341e3df0f2fb5cc851f8", - "reference": "56a60ee4d03ac2be62cb341e3df0f2fb5cc851f8", + "url": "https://api.github.com/repos/Automattic/jetpack-admin-ui/zipball/334858057237be51aa916352c7573fc4c06bbd6c", + "reference": "334858057237be51aa916352c7573fc4c06bbd6c", "shasum": "" }, "require-dev": { - "automattic/jetpack-changelogger": "^3.1", + "automattic/jetpack-changelogger": "^3.3.11", + "automattic/jetpack-logo": "^1.6.3", "automattic/wordbless": "dev-master", - "yoast/phpunit-polyfills": "1.0.3" + "yoast/phpunit-polyfills": "1.1.0" + }, + "suggest": { + "automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package." }, "type": "jetpack-library", "extra": { @@ -78,7 +85,7 @@ "link-template": "https://github.com/Automattic/jetpack-admin-ui/compare/${old}...${new}" }, "branch-alias": { - "dev-master": "0.2.x-dev" + "dev-trunk": "0.2.x-dev" }, "version-constants": { "::PACKAGE_VERSION": "src/class-admin-menu.php" @@ -95,30 +102,30 @@ ], "description": "Generic Jetpack wp-admin UI elements", "support": { - "source": "https://github.com/Automattic/jetpack-admin-ui/tree/v0.2.7" + "source": "https://github.com/Automattic/jetpack-admin-ui/tree/v0.2.24" }, - "time": "2022-04-26T14:33:43+00:00" + "time": "2023-10-30T08:37:02+00:00" }, { "name": "automattic/jetpack-autoloader", - "version": "v2.11.5", + "version": "v2.12.0", "source": { "type": "git", "url": "https://github.com/Automattic/jetpack-autoloader.git", - "reference": "664c7cf0ff94b4f2f7c5b359bef3616822004a04" + "reference": "632b69cfc73ed5505f2b03165e7f68d414d0da12" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Automattic/jetpack-autoloader/zipball/664c7cf0ff94b4f2f7c5b359bef3616822004a04", - "reference": "664c7cf0ff94b4f2f7c5b359bef3616822004a04", + "url": "https://api.github.com/repos/Automattic/jetpack-autoloader/zipball/632b69cfc73ed5505f2b03165e7f68d414d0da12", + "reference": "632b69cfc73ed5505f2b03165e7f68d414d0da12", "shasum": "" }, "require": { "composer-plugin-api": "^1.1 || ^2.0" }, "require-dev": { - "automattic/jetpack-changelogger": "^3.1", - "yoast/phpunit-polyfills": "1.0.3" + "automattic/jetpack-changelogger": "^3.3.11", + "yoast/phpunit-polyfills": "1.1.0" }, "type": "composer-plugin", "extra": { @@ -128,8 +135,11 @@ "changelogger": { "link-template": "https://github.com/Automattic/jetpack-autoloader/compare/v${old}...v${new}" }, + "version-constants": { + "::VERSION": "src/AutoloadGenerator.php" + }, "branch-alias": { - "dev-master": "2.11.x-dev" + "dev-trunk": "2.12.x-dev" } }, "autoload": { @@ -145,27 +155,38 @@ "GPL-2.0-or-later" ], "description": "Creates a custom autoloader for a plugin or theme.", + "keywords": [ + "autoload", + "autoloader", + "composer", + "jetpack", + "plugin", + "wordpress" + ], "support": { - "source": "https://github.com/Automattic/jetpack-autoloader/tree/v2.11.5" + "source": "https://github.com/Automattic/jetpack-autoloader/tree/v2.12.0" }, - "time": "2022-05-18T11:11:44+00:00" + "time": "2023-09-28T18:33:34+00:00" }, { "name": "automattic/jetpack-config", - "version": "v1.9.0", + "version": "v1.15.4", "source": { "type": "git", "url": "https://github.com/Automattic/jetpack-config.git", - "reference": "415d06ba5363b2b204d4763aa4d65bfbdd4b769a" + "reference": "6cf8d61a972530322c9b62f7375fff83342c38f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Automattic/jetpack-config/zipball/415d06ba5363b2b204d4763aa4d65bfbdd4b769a", - "reference": "415d06ba5363b2b204d4763aa4d65bfbdd4b769a", + "url": "https://api.github.com/repos/Automattic/jetpack-config/zipball/6cf8d61a972530322c9b62f7375fff83342c38f9", + "reference": "6cf8d61a972530322c9b62f7375fff83342c38f9", "shasum": "" }, "require-dev": { - "automattic/jetpack-changelogger": "^3.1" + "automattic/jetpack-changelogger": "^3.3.9" + }, + "suggest": { + "automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package." }, "type": "jetpack-library", "extra": { @@ -176,7 +197,7 @@ "link-template": "https://github.com/Automattic/jetpack-config/compare/v${old}...v${new}" }, "branch-alias": { - "dev-master": "1.9.x-dev" + "dev-trunk": "1.15.x-dev" } }, "autoload": { @@ -190,37 +211,40 @@ ], "description": "Jetpack configuration package that initializes other packages and configures Jetpack's functionality. Can be used as a base for all variants of Jetpack package usage.", "support": { - "source": "https://github.com/Automattic/jetpack-config/tree/v1.9.0" + "source": "https://github.com/Automattic/jetpack-config/tree/v1.15.4" }, - "time": "2022-05-18T11:11:22+00:00" + "time": "2023-09-19T18:18:30+00:00" }, { "name": "automattic/jetpack-connection", - "version": "v1.40.5", + "version": "v1.59.0", "source": { "type": "git", "url": "https://github.com/Automattic/jetpack-connection.git", - "reference": "461d33c0aa9b8f706d1b62a317a6c770f990ce4d" + "reference": "eb55a554fe9cbb0d0b7ade54ea6ff965a508b05e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Automattic/jetpack-connection/zipball/461d33c0aa9b8f706d1b62a317a6c770f990ce4d", - "reference": "461d33c0aa9b8f706d1b62a317a6c770f990ce4d", + "url": "https://api.github.com/repos/Automattic/jetpack-connection/zipball/eb55a554fe9cbb0d0b7ade54ea6ff965a508b05e", + "reference": "eb55a554fe9cbb0d0b7ade54ea6ff965a508b05e", "shasum": "" }, "require": { - "automattic/jetpack-a8c-mc-stats": "^1.4", - "automattic/jetpack-admin-ui": "^0.2", - "automattic/jetpack-constants": "^1.6", - "automattic/jetpack-redirect": "^1.7", - "automattic/jetpack-roles": "^1.4", - "automattic/jetpack-status": "^1.13" + "automattic/jetpack-a8c-mc-stats": "^1.4.22", + "automattic/jetpack-admin-ui": "^0.2.24", + "automattic/jetpack-constants": "^1.6.23", + "automattic/jetpack-redirect": "^1.7.27", + "automattic/jetpack-roles": "^1.4.25", + "automattic/jetpack-status": "^1.18.5" }, "require-dev": { - "automattic/jetpack-changelogger": "^3.1", + "automattic/jetpack-changelogger": "^3.3.11", "automattic/wordbless": "@dev", "brain/monkey": "2.6.1", - "yoast/phpunit-polyfills": "1.0.3" + "yoast/phpunit-polyfills": "1.1.0" + }, + "suggest": { + "automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package." }, "type": "jetpack-library", "extra": { @@ -234,7 +258,7 @@ "link-template": "https://github.com/Automattic/jetpack-connection/compare/v${old}...v${new}" }, "branch-alias": { - "dev-master": "1.40.x-dev" + "dev-trunk": "1.59.x-dev" } }, "autoload": { @@ -250,28 +274,31 @@ ], "description": "Everything needed to connect to the Jetpack infrastructure", "support": { - "source": "https://github.com/Automattic/jetpack-connection/tree/v1.40.5" + "source": "https://github.com/Automattic/jetpack-connection/tree/v1.59.0" }, - "time": "2022-06-08T15:15:35+00:00" + "time": "2023-11-08T09:11:43+00:00" }, { "name": "automattic/jetpack-constants", - "version": "v1.6.16", + "version": "v1.6.23", "source": { "type": "git", "url": "https://github.com/Automattic/jetpack-constants.git", - "reference": "f719d15636026c2e47d927a24edc54898d859a0e" + "reference": "0825fb1fa94956f26adebc01be0d716a0fd3ade0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Automattic/jetpack-constants/zipball/f719d15636026c2e47d927a24edc54898d859a0e", - "reference": "f719d15636026c2e47d927a24edc54898d859a0e", + "url": "https://api.github.com/repos/Automattic/jetpack-constants/zipball/0825fb1fa94956f26adebc01be0d716a0fd3ade0", + "reference": "0825fb1fa94956f26adebc01be0d716a0fd3ade0", "shasum": "" }, "require-dev": { - "automattic/jetpack-changelogger": "^3.1", + "automattic/jetpack-changelogger": "^3.3.8", "brain/monkey": "2.6.1", - "yoast/phpunit-polyfills": "1.0.3" + "yoast/phpunit-polyfills": "1.1.0" + }, + "suggest": { + "automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package." }, "type": "jetpack-library", "extra": { @@ -281,7 +308,7 @@ "link-template": "https://github.com/Automattic/jetpack-constants/compare/v${old}...v${new}" }, "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-trunk": "1.6.x-dev" } }, "autoload": { @@ -295,31 +322,34 @@ ], "description": "A wrapper for defining constants in a more testable way.", "support": { - "source": "https://github.com/Automattic/jetpack-constants/tree/v1.6.16" + "source": "https://github.com/Automattic/jetpack-constants/tree/v1.6.23" }, - "time": "2022-04-26T14:33:36+00:00" + "time": "2023-08-23T17:56:35+00:00" }, { "name": "automattic/jetpack-redirect", - "version": "v1.7.15", + "version": "v1.7.27", "source": { "type": "git", "url": "https://github.com/Automattic/jetpack-redirect.git", - "reference": "d9c416ba23831cce2608c6fd689754f15dcb8498" + "reference": "43dd3ae2bef71281fe70f62733bfaa44c988f1b1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Automattic/jetpack-redirect/zipball/d9c416ba23831cce2608c6fd689754f15dcb8498", - "reference": "d9c416ba23831cce2608c6fd689754f15dcb8498", + "url": "https://api.github.com/repos/Automattic/jetpack-redirect/zipball/43dd3ae2bef71281fe70f62733bfaa44c988f1b1", + "reference": "43dd3ae2bef71281fe70f62733bfaa44c988f1b1", "shasum": "" }, "require": { - "automattic/jetpack-status": "^1.13" + "automattic/jetpack-status": "^1.18.4" }, "require-dev": { - "automattic/jetpack-changelogger": "^3.1", + "automattic/jetpack-changelogger": "^3.3.9", "brain/monkey": "2.6.1", - "yoast/phpunit-polyfills": "1.0.3" + "yoast/phpunit-polyfills": "1.1.0" + }, + "suggest": { + "automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package." }, "type": "jetpack-library", "extra": { @@ -329,7 +359,7 @@ "link-template": "https://github.com/Automattic/jetpack-redirect/compare/v${old}...v${new}" }, "branch-alias": { - "dev-master": "1.7.x-dev" + "dev-trunk": "1.7.x-dev" } }, "autoload": { @@ -343,28 +373,31 @@ ], "description": "Utilities to build URLs to the jetpack.com/redirect/ service", "support": { - "source": "https://github.com/Automattic/jetpack-redirect/tree/v1.7.15" + "source": "https://github.com/Automattic/jetpack-redirect/tree/v1.7.27" }, - "time": "2022-05-10T11:30:40+00:00" + "time": "2023-09-19T18:19:22+00:00" }, { "name": "automattic/jetpack-roles", - "version": "v1.4.15", + "version": "v1.4.25", "source": { "type": "git", "url": "https://github.com/Automattic/jetpack-roles.git", - "reference": "6ffbb2fef269334e3528380bfd7a064e3c904dce" + "reference": "708b33f16a879fc2ab5939a972c968c9aeefbe38" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Automattic/jetpack-roles/zipball/6ffbb2fef269334e3528380bfd7a064e3c904dce", - "reference": "6ffbb2fef269334e3528380bfd7a064e3c904dce", + "url": "https://api.github.com/repos/Automattic/jetpack-roles/zipball/708b33f16a879fc2ab5939a972c968c9aeefbe38", + "reference": "708b33f16a879fc2ab5939a972c968c9aeefbe38", "shasum": "" }, "require-dev": { - "automattic/jetpack-changelogger": "^3.1", + "automattic/jetpack-changelogger": "^3.3.9", "brain/monkey": "2.6.1", - "yoast/phpunit-polyfills": "1.0.3" + "yoast/phpunit-polyfills": "1.1.0" + }, + "suggest": { + "automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package." }, "type": "jetpack-library", "extra": { @@ -374,7 +407,7 @@ "link-template": "https://github.com/Automattic/jetpack-roles/compare/v${old}...v${new}" }, "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-trunk": "1.4.x-dev" } }, "autoload": { @@ -388,31 +421,35 @@ ], "description": "Utilities, related with user roles and capabilities.", "support": { - "source": "https://github.com/Automattic/jetpack-roles/tree/v1.4.15" + "source": "https://github.com/Automattic/jetpack-roles/tree/v1.4.25" }, - "time": "2022-04-26T14:33:35+00:00" + "time": "2023-09-19T18:18:38+00:00" }, { "name": "automattic/jetpack-status", - "version": "v1.13.6", + "version": "v1.18.5", "source": { "type": "git", "url": "https://github.com/Automattic/jetpack-status.git", - "reference": "6005840740548864d2a67090d87b59a6f141e5c4" + "reference": "fe08772e2005b8cd78ec5e0d416b73a04ae57c10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Automattic/jetpack-status/zipball/6005840740548864d2a67090d87b59a6f141e5c4", - "reference": "6005840740548864d2a67090d87b59a6f141e5c4", + "url": "https://api.github.com/repos/Automattic/jetpack-status/zipball/fe08772e2005b8cd78ec5e0d416b73a04ae57c10", + "reference": "fe08772e2005b8cd78ec5e0d416b73a04ae57c10", "shasum": "" }, "require": { - "automattic/jetpack-constants": "^1.6" + "automattic/jetpack-constants": "^1.6.23" }, "require-dev": { - "automattic/jetpack-changelogger": "^3.1", + "automattic/jetpack-changelogger": "^3.3.10", + "automattic/jetpack-ip": "^0.1.6", "brain/monkey": "2.6.1", - "yoast/phpunit-polyfills": "1.0.3" + "yoast/phpunit-polyfills": "1.1.0" + }, + "suggest": { + "automattic/jetpack-autoloader": "Allow for better interoperability with other plugins that use this package." }, "type": "jetpack-library", "extra": { @@ -422,7 +459,7 @@ "link-template": "https://github.com/Automattic/jetpack-status/compare/v${old}...v${new}" }, "branch-alias": { - "dev-master": "1.13.x-dev" + "dev-trunk": "1.18.x-dev" } }, "autoload": { @@ -436,22 +473,22 @@ ], "description": "Used to retrieve information about the current status of Jetpack and the site overall.", "support": { - "source": "https://github.com/Automattic/jetpack-status/tree/v1.13.6" + "source": "https://github.com/Automattic/jetpack-status/tree/v1.18.5" }, - "time": "2022-05-24T14:04:09+00:00" + "time": "2023-09-25T19:07:29+00:00" }, { "name": "firebase/php-jwt", - "version": "v6.8.1", + "version": "v6.9.0", "source": { "type": "git", "url": "https://github.com/firebase/php-jwt.git", - "reference": "5dbc8959427416b8ee09a100d7a8588c00fb2e26" + "reference": "f03270e63eaccf3019ef0f32849c497385774e11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/5dbc8959427416b8ee09a100d7a8588c00fb2e26", - "reference": "5dbc8959427416b8ee09a100d7a8588c00fb2e26", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/f03270e63eaccf3019ef0f32849c497385774e11", + "reference": "f03270e63eaccf3019ef0f32849c497385774e11", "shasum": "" }, "require": { @@ -499,22 +536,22 @@ ], "support": { "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.8.1" + "source": "https://github.com/firebase/php-jwt/tree/v6.9.0" }, - "time": "2023-07-14T18:33:00+00:00" + "time": "2023-10-05T00:24:42+00:00" }, { "name": "google/apiclient", - "version": "v2.15.0", + "version": "v2.15.1", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client.git", - "reference": "49787fa30b8d8313146a61efbf77ed1fede723c2" + "reference": "7a95ed29e4b6c6859d2d22300c5455a92e2622ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/49787fa30b8d8313146a61efbf77ed1fede723c2", - "reference": "49787fa30b8d8313146a61efbf77ed1fede723c2", + "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/7a95ed29e4b6c6859d2d22300c5455a92e2622ad", + "reference": "7a95ed29e4b6c6859d2d22300c5455a92e2622ad", "shasum": "" }, "require": { @@ -525,7 +562,7 @@ "guzzlehttp/psr7": "^1.8.4||^2.2.1", "monolog/monolog": "^2.9||^3.0", "php": "^7.4|^8.0", - "phpseclib/phpseclib": "^3.0.2" + "phpseclib/phpseclib": "^3.0.19" }, "require-dev": { "cache/filesystem-adapter": "^1.1", @@ -568,22 +605,22 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client/issues", - "source": "https://github.com/googleapis/google-api-php-client/tree/v2.15.0" + "source": "https://github.com/googleapis/google-api-php-client/tree/v2.15.1" }, - "time": "2023-05-18T13:51:33+00:00" + "time": "2023-09-13T21:46:39+00:00" }, { "name": "google/apiclient-services", - "version": "v0.312.0", + "version": "v0.323.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", - "reference": "45d47fed73b28254c511882bc743b1690a99558d" + "reference": "d5497d30ddfafe7592102ca48bedaf222a4ca7a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/45d47fed73b28254c511882bc743b1690a99558d", - "reference": "45d47fed73b28254c511882bc743b1690a99558d", + "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/d5497d30ddfafe7592102ca48bedaf222a4ca7a6", + "reference": "d5497d30ddfafe7592102ca48bedaf222a4ca7a6", "shasum": "" }, "require": { @@ -612,22 +649,22 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.312.0" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.323.0" }, - "time": "2023-08-14T00:56:12+00:00" + "time": "2023-11-06T01:08:38+00:00" }, { "name": "google/auth", - "version": "v1.28.0", + "version": "v1.32.1", "source": { "type": "git", "url": "https://github.com/googleapis/google-auth-library-php.git", - "reference": "07f7f6305f1b7df32b2acf6e101c1225c839c7ac" + "reference": "999e9ce8b9d17914f04e1718271a0a46da4de2f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/07f7f6305f1b7df32b2acf6e101c1225c839c7ac", - "reference": "07f7f6305f1b7df32b2acf6e101c1225c839c7ac", + "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/999e9ce8b9d17914f04e1718271a0a46da4de2f3", + "reference": "999e9ce8b9d17914f04e1718271a0a46da4de2f3", "shasum": "" }, "require": { @@ -639,8 +676,8 @@ "psr/http-message": "^1.1||^2.0" }, "require-dev": { - "guzzlehttp/promises": "^1.3", - "kelvinmo/simplejwt": "0.7.0", + "guzzlehttp/promises": "^2.0", + "kelvinmo/simplejwt": "0.7.1", "phpseclib/phpseclib": "^3.0", "phpspec/prophecy-phpunit": "^2.0", "phpunit/phpunit": "^9.0.0", @@ -670,22 +707,22 @@ "support": { "docs": "https://googleapis.github.io/google-auth-library-php/main/", "issues": "https://github.com/googleapis/google-auth-library-php/issues", - "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.28.0" + "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.32.1" }, - "time": "2023-05-11T21:58:18+00:00" + "time": "2023-10-17T21:13:22+00:00" }, { "name": "google/common-protos", - "version": "v4.2.0", + "version": "v4.4.0", "source": { "type": "git", "url": "https://github.com/googleapis/common-protos-php.git", - "reference": "5d9e21141d94329d69d45a8c7a0cdeafd1a143f3" + "reference": "04b6c213e0add963dab058329caf2d2d9014129a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/common-protos-php/zipball/5d9e21141d94329d69d45a8c7a0cdeafd1a143f3", - "reference": "5d9e21141d94329d69d45a8c7a0cdeafd1a143f3", + "url": "https://api.github.com/repos/googleapis/common-protos-php/zipball/04b6c213e0add963dab058329caf2d2d9014129a", + "reference": "04b6c213e0add963dab058329caf2d2d9014129a", "shasum": "" }, "require": { @@ -722,22 +759,22 @@ ], "support": { "issues": "https://github.com/googleapis/common-protos-php/issues", - "source": "https://github.com/googleapis/common-protos-php/tree/v4.2.0" + "source": "https://github.com/googleapis/common-protos-php/tree/v4.4.0" }, - "time": "2023-07-25T21:51:55+00:00" + "time": "2023-10-02T18:14:18+00:00" }, { "name": "google/gax", - "version": "v1.22.1", + "version": "v1.25.0", "source": { "type": "git", "url": "https://github.com/googleapis/gax-php.git", - "reference": "2566bce7081f17e4f4c35a215864c6d4a62f010f" + "reference": "8f07f56f8d14e784777020cd73cfde518bd7dd33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/googleapis/gax-php/zipball/2566bce7081f17e4f4c35a215864c6d4a62f010f", - "reference": "2566bce7081f17e4f4c35a215864c6d4a62f010f", + "url": "https://api.github.com/repos/googleapis/gax-php/zipball/8f07f56f8d14e784777020cd73cfde518bd7dd33", + "reference": "8f07f56f8d14e784777020cd73cfde518bd7dd33", "shasum": "" }, "require": { @@ -777,9 +814,9 @@ ], "support": { "issues": "https://github.com/googleapis/gax-php/issues", - "source": "https://github.com/googleapis/gax-php/tree/v1.22.1" + "source": "https://github.com/googleapis/gax-php/tree/v1.25.0" }, - "time": "2023-08-04T14:32:15+00:00" + "time": "2023-11-02T22:05:32+00:00" }, { "name": "google/longrunning", @@ -827,16 +864,16 @@ }, { "name": "google/protobuf", - "version": "v3.24.0", + "version": "v3.25.0", "source": { "type": "git", "url": "https://github.com/protocolbuffers/protobuf-php.git", - "reference": "bfa8d627de8464634e6e3b5943f6354baa9cedd2" + "reference": "e5a021e653ee3a7a78760caefa605b4ec31bba80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/bfa8d627de8464634e6e3b5943f6354baa9cedd2", - "reference": "bfa8d627de8464634e6e3b5943f6354baa9cedd2", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/e5a021e653ee3a7a78760caefa605b4ec31bba80", + "reference": "e5a021e653ee3a7a78760caefa605b4ec31bba80", "shasum": "" }, "require": { @@ -865,9 +902,9 @@ "proto" ], "support": { - "source": "https://github.com/protocolbuffers/protobuf-php/tree/v3.24.0" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v3.25.0" }, - "time": "2023-08-08T21:14:02+00:00" + "time": "2023-11-01T22:12:38+00:00" }, { "name": "googleads/google-ads-php", @@ -934,22 +971,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.7.0", + "version": "7.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5" + "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5", - "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1110f66a6530a40fe7aea0378fe608ee2b2248f9", + "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0", - "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -1040,7 +1077,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.7.0" + "source": "https://github.com/guzzle/guzzle/tree/7.8.0" }, "funding": [ { @@ -1056,7 +1093,7 @@ "type": "tidelift" } ], - "time": "2023-05-21T14:04:53+00:00" + "time": "2023-08-27T10:20:53+00:00" }, { "name": "guzzlehttp/promises", @@ -1143,16 +1180,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "2.6.0", + "version": "2.6.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77" + "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/8bd7c33a0734ae1c5d074360512beb716bef3f77", - "reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/be45764272e8873c72dbe3d2edcfdfcc3bc9f727", + "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727", "shasum": "" }, "require": { @@ -1239,7 +1276,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.6.0" + "source": "https://github.com/guzzle/psr7/tree/2.6.1" }, "funding": [ { @@ -1255,7 +1292,7 @@ "type": "tidelift" } ], - "time": "2023-08-03T15:06:02+00:00" + "time": "2023-08-27T10:13:57+00:00" }, { "name": "league/container", @@ -1338,19 +1375,20 @@ }, { "name": "league/iso3166", - "version": "4.1.0", + "version": "4.3.1", "source": { "type": "git", "url": "https://github.com/thephpleague/iso3166.git", - "reference": "a0dd2a1d956f85811f9c667a1744d822fb2c63d8" + "reference": "11703e0313f34920add11c0228f0dd43ebd10f9a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/iso3166/zipball/a0dd2a1d956f85811f9c667a1744d822fb2c63d8", - "reference": "a0dd2a1d956f85811f9c667a1744d822fb2c63d8", + "url": "https://api.github.com/repos/thephpleague/iso3166/zipball/11703e0313f34920add11c0228f0dd43ebd10f9a", + "reference": "11703e0313f34920add11c0228f0dd43ebd10f9a", "shasum": "" }, "require": { + "ext-mbstring": "*", "php": "^7.3|^8.0" }, "require-dev": { @@ -1391,20 +1429,20 @@ "issues": "https://github.com/thephpleague/iso3166/issues", "source": "https://github.com/thephpleague/iso3166" }, - "time": "2022-09-07T09:14:19+00:00" + "time": "2023-09-11T07:59:36+00:00" }, { "name": "monolog/monolog", - "version": "2.9.1", + "version": "2.9.2", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1" + "reference": "437cb3628f4cf6042cc10ae97fc2b8472e48ca1f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f259e2b15fb95494c83f52d3caad003bbf5ffaa1", - "reference": "f259e2b15fb95494c83f52d3caad003bbf5ffaa1", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/437cb3628f4cf6042cc10ae97fc2b8472e48ca1f", + "reference": "437cb3628f4cf6042cc10ae97fc2b8472e48ca1f", "shasum": "" }, "require": { @@ -1481,7 +1519,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/2.9.1" + "source": "https://github.com/Seldaek/monolog/tree/2.9.2" }, "funding": [ { @@ -1493,7 +1531,7 @@ "type": "tidelift" } ], - "time": "2023-02-06T13:44:46+00:00" + "time": "2023-10-27T15:25:26+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -1676,16 +1714,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.21", + "version": "3.0.33", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "4580645d3fc05c189024eb3b834c6c1e4f0f30a1" + "reference": "33fa69b2514a61138dd48e7a49f99445711e0ad0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/4580645d3fc05c189024eb3b834c6c1e4f0f30a1", - "reference": "4580645d3fc05c189024eb3b834c6c1e4f0f30a1", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/33fa69b2514a61138dd48e7a49f99445711e0ad0", + "reference": "33fa69b2514a61138dd48e7a49f99445711e0ad0", "shasum": "" }, "require": { @@ -1766,7 +1804,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.21" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.33" }, "funding": [ { @@ -1782,7 +1820,7 @@ "type": "tidelift" } ], - "time": "2023-07-09T15:24:48+00:00" + "time": "2023-10-21T14:00:39+00:00" }, { "name": "psr/cache", @@ -1883,16 +1921,16 @@ }, { "name": "psr/http-client", - "version": "1.0.2", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/php-fig/http-client.git", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31" + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31", - "reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", "shasum": "" }, "require": { @@ -1929,9 +1967,9 @@ "psr-18" ], "support": { - "source": "https://github.com/php-fig/http-client/tree/1.0.2" + "source": "https://github.com/php-fig/http-client" }, - "time": "2023-04-10T20:12:12+00:00" + "time": "2023-09-23T14:17:50+00:00" }, { "name": "psr/http-factory", @@ -2204,16 +2242,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", "shasum": "" }, "require": { @@ -2228,7 +2266,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -2266,7 +2304,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" }, "funding": [ { @@ -2282,20 +2320,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", "shasum": "" }, "require": { @@ -2307,7 +2345,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -2350,7 +2388,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" }, "funding": [ { @@ -2366,20 +2404,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + "reference": "42292d99c55abe617799667f454222c54c60e229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", "shasum": "" }, "require": { @@ -2394,7 +2432,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -2433,7 +2471,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" }, "funding": [ { @@ -2449,20 +2487,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-07-28T09:04:16+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.26.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85" + "reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/e440d35fa0286f77fb45b79a03fedbeda9307e85", - "reference": "e440d35fa0286f77fb45b79a03fedbeda9307e85", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/fe2f306d1d9d346a7fee353d0d5012e401e984b5", + "reference": "fe2f306d1d9d346a7fee353d0d5012e401e984b5", "shasum": "" }, "require": { @@ -2471,7 +2509,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.26-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -2512,7 +2550,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php73/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-php73/tree/v1.28.0" }, "funding": [ { @@ -2528,20 +2566,20 @@ "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", "shasum": "" }, "require": { @@ -2550,7 +2588,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -2595,7 +2633,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" }, "funding": [ { @@ -2611,20 +2649,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.26.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1" + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/13f6d1271c663dc5ae9fb843a8f16521db7687a1", - "reference": "13f6d1271c663dc5ae9fb843a8f16521db7687a1", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", "shasum": "" }, "require": { @@ -2633,7 +2671,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.26-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -2674,7 +2712,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.26.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" }, "funding": [ { @@ -2690,20 +2728,20 @@ "type": "tidelift" } ], - "time": "2022-05-24T11:49:31+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/translation-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "1211df0afa701e45a04253110e959d4af4ef0f07" + "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/1211df0afa701e45a04253110e959d4af4ef0f07", - "reference": "1211df0afa701e45a04253110e959d4af4ef0f07", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/136b19dd05cdf0709db6537d058bcab6dd6e2dbe", + "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe", "shasum": "" }, "require": { @@ -2752,7 +2790,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/translation-contracts/tree/v2.5.2" }, "funding": [ { @@ -2768,20 +2806,20 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-06-27T16:58:25+00:00" }, { "name": "symfony/validator", - "version": "v5.4.8", + "version": "v5.4.30", "source": { "type": "git", "url": "https://github.com/symfony/validator.git", - "reference": "bdc6d04ba95c73ccbf906b4ad9b8775c738d83ad" + "reference": "ce65d7802d78e43d46669bfa08521bf6104880f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/validator/zipball/bdc6d04ba95c73ccbf906b4ad9b8775c738d83ad", - "reference": "bdc6d04ba95c73ccbf906b4ad9b8775c738d83ad", + "url": "https://api.github.com/repos/symfony/validator/zipball/ce65d7802d78e43d46669bfa08521bf6104880f0", + "reference": "ce65d7802d78e43d46669bfa08521bf6104880f0", "shasum": "" }, "require": { @@ -2798,7 +2836,6 @@ "doctrine/annotations": "<1.13", "doctrine/cache": "<1.11", "doctrine/lexer": "<1.1", - "phpunit/phpunit": "<5.4.3", "symfony/dependency-injection": "<4.4", "symfony/expression-language": "<5.1", "symfony/http-kernel": "<4.4", @@ -2808,9 +2845,9 @@ "symfony/yaml": "<4.4" }, "require-dev": { - "doctrine/annotations": "^1.13", + "doctrine/annotations": "^1.13|^2", "doctrine/cache": "^1.11|^2.0", - "egulias/email-validator": "^2.1.10|^3", + "egulias/email-validator": "^2.1.10|^3|^4", "symfony/cache": "^4.4|^5.0|^6.0", "symfony/config": "^4.4|^5.0|^6.0", "symfony/console": "^4.4|^5.0|^6.0", @@ -2865,7 +2902,7 @@ "description": "Provides tools to validate values", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/validator/tree/v5.4.8" + "source": "https://github.com/symfony/validator/tree/v5.4.30" }, "funding": [ { @@ -2881,7 +2918,7 @@ "type": "tidelift" } ], - "time": "2022-04-15T08:07:45+00:00" + "time": "2023-10-27T07:38:31+00:00" } ], "packages-dev": [ @@ -3090,16 +3127,16 @@ }, { "name": "gettext/gettext", - "version": "v4.8.8", + "version": "v4.8.11", "source": { "type": "git", "url": "https://github.com/php-gettext/Gettext.git", - "reference": "302a00aa9d6762c92c884d879c15d3ed05d6a37d" + "reference": "b632aaf5e4579d0b2ae8bc61785e238bff4c5156" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-gettext/Gettext/zipball/302a00aa9d6762c92c884d879c15d3ed05d6a37d", - "reference": "302a00aa9d6762c92c884d879c15d3ed05d6a37d", + "url": "https://api.github.com/repos/php-gettext/Gettext/zipball/b632aaf5e4579d0b2ae8bc61785e238bff4c5156", + "reference": "b632aaf5e4579d0b2ae8bc61785e238bff4c5156", "shasum": "" }, "require": { @@ -3151,7 +3188,7 @@ "support": { "email": "oom@oscarotero.com", "issues": "https://github.com/oscarotero/Gettext/issues", - "source": "https://github.com/php-gettext/Gettext/tree/v4.8.8" + "source": "https://github.com/php-gettext/Gettext/tree/v4.8.11" }, "funding": [ { @@ -3167,7 +3204,7 @@ "type": "patreon" } ], - "time": "2022-12-08T11:59:50+00:00" + "time": "2023-08-14T15:15:05+00:00" }, { "name": "gettext/languages", @@ -3245,16 +3282,16 @@ }, { "name": "mck89/peast", - "version": "v1.15.1", + "version": "v1.15.4", "source": { "type": "git", "url": "https://github.com/mck89/peast.git", - "reference": "cf06286910b7efc9dce7503553ebee314df3d3d3" + "reference": "1df4dc28a6b5bb7ab117ab073c1712256e954e18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mck89/peast/zipball/cf06286910b7efc9dce7503553ebee314df3d3d3", - "reference": "cf06286910b7efc9dce7503553ebee314df3d3d3", + "url": "https://api.github.com/repos/mck89/peast/zipball/1df4dc28a6b5bb7ab117ab073c1712256e954e18", + "reference": "1df4dc28a6b5bb7ab117ab073c1712256e954e18", "shasum": "" }, "require": { @@ -3267,13 +3304,12 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15.1-dev" + "dev-master": "1.15.4-dev" } }, "autoload": { "psr-4": { - "Peast\\": "lib/Peast/", - "Peast\\test\\": "test/Peast/" + "Peast\\": "lib/Peast/" } }, "notification-url": "https://packagist.org/downloads/", @@ -3289,9 +3325,9 @@ "description": "Peast is PHP library that generates AST for JavaScript code", "support": { "issues": "https://github.com/mck89/peast/issues", - "source": "https://github.com/mck89/peast/tree/v1.15.1" + "source": "https://github.com/mck89/peast/tree/v1.15.4" }, - "time": "2023-01-21T13:18:17+00:00" + "time": "2023-08-12T08:29:29+00:00" }, { "name": "mustache/mustache", @@ -3345,16 +3381,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.11.0", + "version": "1.11.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", - "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", "shasum": "" }, "require": { @@ -3392,7 +3428,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" }, "funding": [ { @@ -3400,20 +3436,20 @@ "type": "tidelift" } ], - "time": "2022-03-03T13:19:32+00:00" + "time": "2023-03-08T13:26:56+00:00" }, { "name": "nikic/php-parser", - "version": "v4.15.3", + "version": "v4.17.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039" + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/570e980a201d8ed0236b0a62ddf2c9cbb2034039", - "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", "shasum": "" }, "require": { @@ -3454,9 +3490,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.3" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" }, - "time": "2023-01-16T22:05:37+00:00" + "time": "2023-08-13T19:53:39+00:00" }, { "name": "phar-io/manifest", @@ -3571,23 +3607,23 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.24", + "version": "9.2.29", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2cf940ebc6355a9d430462811b5aaa308b174bed" + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2cf940ebc6355a9d430462811b5aaa308b174bed", - "reference": "2cf940ebc6355a9d430462811b5aaa308b174bed", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6a3a87ac2bbe33b25042753df8195ba4aa534c76", + "reference": "6a3a87ac2bbe33b25042753df8195ba4aa534c76", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^4.14", + "nikic/php-parser": "^4.15", "php": ">=7.3", "phpunit/php-file-iterator": "^3.0.3", "phpunit/php-text-template": "^2.0.2", @@ -3602,8 +3638,8 @@ "phpunit/phpunit": "^9.3" }, "suggest": { - "ext-pcov": "*", - "ext-xdebug": "*" + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "type": "library", "extra": { @@ -3636,7 +3672,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.24" + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.29" }, "funding": [ { @@ -3644,7 +3681,7 @@ "type": "github" } ], - "time": "2023-01-26T08:26:55+00:00" + "time": "2023-09-19T04:57:46+00:00" }, { "name": "phpunit/php-file-iterator", @@ -3889,16 +3926,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.28", + "version": "9.6.13", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "954ca3113a03bf780d22f07bf055d883ee04b65e" + "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/954ca3113a03bf780d22f07bf055d883ee04b65e", - "reference": "954ca3113a03bf780d22f07bf055d883ee04b65e", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f3d767f7f9e191eab4189abe41ab37797e30b1be", + "reference": "f3d767f7f9e191eab4189abe41ab37797e30b1be", "shasum": "" }, "require": { @@ -3913,7 +3950,7 @@ "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.13", + "phpunit/php-code-coverage": "^9.2.28", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", @@ -3931,8 +3968,8 @@ "sebastian/version": "^3.0.2" }, "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "ext-soap": "To be able to generate mocks based on WSDL files", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" }, "bin": [ "phpunit" @@ -3940,7 +3977,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.5-dev" + "dev-master": "9.6-dev" } }, "autoload": { @@ -3971,7 +4008,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.28" + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.13" }, "funding": [ { @@ -3987,67 +4025,7 @@ "type": "tidelift" } ], - "time": "2023-01-14T12:32:24+00:00" - }, - { - "name": "rmccue/requests", - "version": "v1.8.1", - "source": { - "type": "git", - "url": "https://github.com/WordPress/Requests.git", - "reference": "82e6936366eac3af4d836c18b9d8c31028fe4cd5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/WordPress/Requests/zipball/82e6936366eac3af4d836c18b9d8c31028fe4cd5", - "reference": "82e6936366eac3af4d836c18b9d8c31028fe4cd5", - "shasum": "" - }, - "require": { - "php": ">=5.2" - }, - "require-dev": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.7", - "php-parallel-lint/php-console-highlighter": "^0.5.0", - "php-parallel-lint/php-parallel-lint": "^1.3", - "phpcompatibility/php-compatibility": "^9.0", - "phpunit/phpunit": "^4.8 || ^5.7 || ^6.5 || ^7.5", - "requests/test-server": "dev-master", - "squizlabs/php_codesniffer": "^3.5", - "wp-coding-standards/wpcs": "^2.0" - }, - "type": "library", - "autoload": { - "psr-0": { - "Requests": "library/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "ISC" - ], - "authors": [ - { - "name": "Ryan McCue", - "homepage": "http://ryanmccue.info" - } - ], - "description": "A HTTP library written in PHP, for human beings.", - "homepage": "http://github.com/WordPress/Requests", - "keywords": [ - "curl", - "fsockopen", - "http", - "idna", - "ipv6", - "iri", - "sockets" - ], - "support": { - "issues": "https://github.com/WordPress/Requests/issues", - "source": "https://github.com/WordPress/Requests/tree/v1.8.1" - }, - "time": "2021-06-04T09:56:25+00:00" + "time": "2023-09-19T05:39:22+00:00" }, { "name": "sebastian/cli-parser", @@ -4349,16 +4327,16 @@ }, { "name": "sebastian/diff", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", - "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/74be17022044ebaaecfdf0c5cd504fc9cd5a7131", + "reference": "74be17022044ebaaecfdf0c5cd504fc9cd5a7131", "shasum": "" }, "require": { @@ -4403,7 +4381,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.5" }, "funding": [ { @@ -4411,20 +4389,20 @@ "type": "github" } ], - "time": "2020-10-26T13:10:38+00:00" + "time": "2023-05-07T05:35:17+00:00" }, { "name": "sebastian/environment", - "version": "5.1.4", + "version": "5.1.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7" + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/1b5dff7bb151a4db11d49d90e5408e4e938270f7", - "reference": "1b5dff7bb151a4db11d49d90e5408e4e938270f7", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", "shasum": "" }, "require": { @@ -4466,7 +4444,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.4" + "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" }, "funding": [ { @@ -4474,7 +4452,7 @@ "type": "github" } ], - "time": "2022-04-03T09:37:03+00:00" + "time": "2023-02-03T06:03:51+00:00" }, { "name": "sebastian/exporter", @@ -4555,16 +4533,16 @@ }, { "name": "sebastian/global-state", - "version": "5.0.5", + "version": "5.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2" + "reference": "bde739e7565280bda77be70044ac1047bc007e34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/0ca8db5a5fc9c8646244e629625ac486fa286bf2", - "reference": "0ca8db5a5fc9c8646244e629625ac486fa286bf2", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bde739e7565280bda77be70044ac1047bc007e34", + "reference": "bde739e7565280bda77be70044ac1047bc007e34", "shasum": "" }, "require": { @@ -4607,7 +4585,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.5" + "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.6" }, "funding": [ { @@ -4615,7 +4593,7 @@ "type": "github" } ], - "time": "2022-02-14T08:28:10+00:00" + "time": "2023-08-02T09:26:13+00:00" }, { "name": "sebastian/lines-of-code", @@ -4788,16 +4766,16 @@ }, { "name": "sebastian/recursion-context", - "version": "4.0.4", + "version": "4.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172" + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/cd9d8cf3c5804de4341c283ed787f099f5506172", - "reference": "cd9d8cf3c5804de4341c283ed787f099f5506172", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", + "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", "shasum": "" }, "require": { @@ -4836,10 +4814,10 @@ } ], "description": "Provides functionality to recursively process PHP variables", - "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" }, "funding": [ { @@ -4847,7 +4825,7 @@ "type": "github" } ], - "time": "2020-10-26T13:17:30+00:00" + "time": "2023-02-03T06:07:39+00:00" }, { "name": "sebastian/resource-operations", @@ -4906,16 +4884,16 @@ }, { "name": "sebastian/type", - "version": "3.2.0", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e" + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", - "reference": "fb3fe09c5f0bae6bc27ef3ce933a1e0ed9464b6e", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", "shasum": "" }, "require": { @@ -4950,7 +4928,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.0" + "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" }, "funding": [ { @@ -4958,7 +4936,7 @@ "type": "github" } ], - "time": "2022-09-12T14:47:03+00:00" + "time": "2023-02-03T06:13:03+00:00" }, { "name": "sebastian/version", @@ -5071,16 +5049,16 @@ }, { "name": "symfony/finder", - "version": "v5.4.19", + "version": "v5.4.27", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "6071aebf810ad13fe8200c224f36103abb37cf1f" + "reference": "ff4bce3c33451e7ec778070e45bd23f74214cd5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/6071aebf810ad13fe8200c224f36103abb37cf1f", - "reference": "6071aebf810ad13fe8200c224f36103abb37cf1f", + "url": "https://api.github.com/repos/symfony/finder/zipball/ff4bce3c33451e7ec778070e45bd23f74214cd5d", + "reference": "ff4bce3c33451e7ec778070e45bd23f74214cd5d", "shasum": "" }, "require": { @@ -5114,7 +5092,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.4.19" + "source": "https://github.com/symfony/finder/tree/v5.4.27" }, "funding": [ { @@ -5130,7 +5108,7 @@ "type": "tidelift" } ], - "time": "2023-01-14T19:14:44+00:00" + "time": "2023-07-31T08:02:31+00:00" }, { "name": "theseer/tokenizer", @@ -5184,16 +5162,16 @@ }, { "name": "wp-cli/i18n-command", - "version": "v2.4.1", + "version": "v2.4.4", "source": { "type": "git", "url": "https://github.com/wp-cli/i18n-command.git", - "reference": "22f7e6aa6ba23d0b50c45c75386c8151b991477e" + "reference": "7d82e675f271359b1af614e6325d8eeaeb7d7474" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/22f7e6aa6ba23d0b50c45c75386c8151b991477e", - "reference": "22f7e6aa6ba23d0b50c45c75386c8151b991477e", + "url": "https://api.github.com/repos/wp-cli/i18n-command/zipball/7d82e675f271359b1af614e6325d8eeaeb7d7474", + "reference": "7d82e675f271359b1af614e6325d8eeaeb7d7474", "shasum": "" }, "require": { @@ -5204,7 +5182,7 @@ }, "require-dev": { "wp-cli/scaffold-command": "^1.2 || ^2", - "wp-cli/wp-cli-tests": "^3.1" + "wp-cli/wp-cli-tests": "^4" }, "suggest": { "ext-json": "Used for reading and generating JSON translation files", @@ -5246,9 +5224,9 @@ "homepage": "https://github.com/wp-cli/i18n-command", "support": { "issues": "https://github.com/wp-cli/i18n-command/issues", - "source": "https://github.com/wp-cli/i18n-command/tree/v2.4.1" + "source": "https://github.com/wp-cli/i18n-command/tree/v2.4.4" }, - "time": "2022-12-09T19:09:17+00:00" + "time": "2023-08-30T18:00:10+00:00" }, { "name": "wp-cli/mustangostang-spyc", @@ -5303,16 +5281,16 @@ }, { "name": "wp-cli/php-cli-tools", - "version": "v0.11.17", + "version": "v0.11.21", "source": { "type": "git", "url": "https://github.com/wp-cli/php-cli-tools.git", - "reference": "f6be76b7c4ee2ef93c9531b8a37bdb7ce42c3728" + "reference": "b3457a8d60cd0b1c48cab76ad95df136d266f0b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/php-cli-tools/zipball/f6be76b7c4ee2ef93c9531b8a37bdb7ce42c3728", - "reference": "f6be76b7c4ee2ef93c9531b8a37bdb7ce42c3728", + "url": "https://api.github.com/repos/wp-cli/php-cli-tools/zipball/b3457a8d60cd0b1c48cab76ad95df136d266f0b6", + "reference": "b3457a8d60cd0b1c48cab76ad95df136d266f0b6", "shasum": "" }, "require": { @@ -5320,7 +5298,7 @@ }, "require-dev": { "roave/security-advisories": "dev-latest", - "wp-cli/wp-cli-tests": "^3.1.6" + "wp-cli/wp-cli-tests": "^4" }, "type": "library", "extra": { @@ -5360,29 +5338,28 @@ ], "support": { "issues": "https://github.com/wp-cli/php-cli-tools/issues", - "source": "https://github.com/wp-cli/php-cli-tools/tree/v0.11.17" + "source": "https://github.com/wp-cli/php-cli-tools/tree/v0.11.21" }, - "time": "2023-01-12T01:18:21+00:00" + "time": "2023-09-29T15:28:10+00:00" }, { "name": "wp-cli/wp-cli", - "version": "v2.7.1", + "version": "v2.9.0", "source": { "type": "git", "url": "https://github.com/wp-cli/wp-cli.git", - "reference": "1ddc754f1c15e56fb2cdd1a4e82bd0ec6ca32a76" + "reference": "8a3befba2d947fbf5cc6d1941edf2dd99da4d4b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wp-cli/wp-cli/zipball/1ddc754f1c15e56fb2cdd1a4e82bd0ec6ca32a76", - "reference": "1ddc754f1c15e56fb2cdd1a4e82bd0ec6ca32a76", + "url": "https://api.github.com/repos/wp-cli/wp-cli/zipball/8a3befba2d947fbf5cc6d1941edf2dd99da4d4b7", + "reference": "8a3befba2d947fbf5cc6d1941edf2dd99da4d4b7", "shasum": "" }, "require": { "ext-curl": "*", "mustache/mustache": "^2.14.1", "php": "^5.6 || ^7.0 || ^8.0", - "rmccue/requests": "^1.8", "symfony/finder": ">2.7", "wp-cli/mustangostang-spyc": "^0.6.3", "wp-cli/php-cli-tools": "~0.11.2" @@ -5393,7 +5370,7 @@ "wp-cli/entity-command": "^1.2 || ^2", "wp-cli/extension-command": "^1.1 || ^2", "wp-cli/package-command": "^1 || ^2", - "wp-cli/wp-cli-tests": "^3.1.6" + "wp-cli/wp-cli-tests": "^4.0.1" }, "suggest": { "ext-readline": "Include for a better --prompt implementation", @@ -5406,7 +5383,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8.x-dev" + "dev-main": "2.9.x-dev" } }, "autoload": { @@ -5433,7 +5410,7 @@ "issues": "https://github.com/wp-cli/wp-cli/issues", "source": "https://github.com/wp-cli/wp-cli" }, - "time": "2022-10-17T23:10:42+00:00" + "time": "2023-10-25T09:06:37+00:00" }, { "name": "wp-coding-standards/wpcs", @@ -5488,16 +5465,16 @@ }, { "name": "yoast/phpunit-polyfills", - "version": "1.0.3", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/Yoast/PHPUnit-Polyfills.git", - "reference": "5ea3536428944955f969bc764bbe09738e151ada" + "reference": "224e4a1329c03d8bad520e3fc4ec980034a4b212" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/5ea3536428944955f969bc764bbe09738e151ada", - "reference": "5ea3536428944955f969bc764bbe09738e151ada", + "url": "https://api.github.com/repos/Yoast/PHPUnit-Polyfills/zipball/224e4a1329c03d8bad520e3fc4ec980034a4b212", + "reference": "224e4a1329c03d8bad520e3fc4ec980034a4b212", "shasum": "" }, "require": { @@ -5505,13 +5482,12 @@ "phpunit/phpunit": "^4.8.36 || ^5.7.21 || ^6.0 || ^7.0 || ^8.0 || ^9.0" }, "require-dev": { - "yoast/yoastcs": "^2.2.0" + "yoast/yoastcs": "^2.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "1.x-dev", - "dev-develop": "1.x-dev" + "dev-main": "2.x-dev" } }, "autoload": { @@ -5545,7 +5521,7 @@ "issues": "https://github.com/Yoast/PHPUnit-Polyfills/issues", "source": "https://github.com/Yoast/PHPUnit-Polyfills" }, - "time": "2021-11-23T01:37:03+00:00" + "time": "2023-08-19T14:25:08+00:00" } ], "aliases": [], @@ -5561,5 +5537,5 @@ "platform-overrides": { "php": "7.4.30" }, - "plugin-api-version": "2.2.0" + "plugin-api-version": "2.6.0" } From 2f81f354e3e61343765882e5800d5025f1bba053 Mon Sep 17 00:00:00 2001 From: Jorge M Date: Fri, 10 Nov 2023 20:33:54 +0100 Subject: [PATCH 011/135] Fix eslint errors --- src/Integration/WPCOMProxy.php | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/Integration/WPCOMProxy.php b/src/Integration/WPCOMProxy.php index 3380e98d2c..9829d3cf43 100644 --- a/src/Integration/WPCOMProxy.php +++ b/src/Integration/WPCOMProxy.php @@ -59,7 +59,7 @@ public function register(): void { // Allow to filter by gla_syncable. add_filter( 'woocommerce_rest_query_vars', - function( $valid_vars ) { + function ( $valid_vars ) { $valid_vars[] = 'gla_syncable'; return $valid_vars; } @@ -68,7 +68,6 @@ function( $valid_vars ) { foreach ( array_keys( self::$post_types_to_be_filter ) as $object_type ) { $this->register_object_types_filter( $object_type ); } - } /** @@ -92,7 +91,6 @@ protected function register_object_types_filter( string $object_type ): void { 10, 2 ); - } /** @@ -110,12 +108,12 @@ protected function should_filter_data( WP_REST_Request $request ): bool { * Check if a single item is syncable. * * @param WP_REST_Response $response The response object. - * @param mixed $object The object. + * @param mixed $item The item. * @param WP_REST_Request $request The request object. * * @return WP_REST_Response The response object updated. */ - public function check_item_is_syncable( $response, $object, WP_REST_Request $request ): WP_REST_Response { + public function check_item_is_syncable( $response, $item, WP_REST_Request $request ): WP_REST_Response { if ( ! $this->should_filter_data( $request ) ) { return $response; } @@ -150,7 +148,6 @@ public function check_item_is_syncable( $response, $object, WP_REST_Request $req ], 403 ); - } /** @@ -182,12 +179,12 @@ public function filter_by_metaquery( array $args, WP_REST_Request $request ): ar * Filter the metadata of an object. * * @param WP_REST_Response $response The response object. - * @param mixed $object The object. + * @param mixed $item The item. * @param WP_REST_Request $request The request object. * * @return WP_REST_Response The response object updated. */ - public function filter_metadata( WP_REST_Response $response, $object, WP_REST_Request $request ): WP_REST_Response { + public function filter_metadata( WP_REST_Response $response, $item, WP_REST_Request $request ): WP_REST_Response { if ( ! $this->should_filter_data( $request ) ) { return $response; } @@ -209,5 +206,4 @@ public function filter_metadata( WP_REST_Response $response, $object, WP_REST_Re return $response; } - } From 686b966e2eb448c71e3b38efb004925ffe5699c1 Mon Sep 17 00:00:00 2001 From: Jorge M Date: Fri, 10 Nov 2023 20:38:54 +0100 Subject: [PATCH 012/135] Fix phpcs tests --- tests/Unit/Integration/WPCOMProxyTest.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/Unit/Integration/WPCOMProxyTest.php b/tests/Unit/Integration/WPCOMProxyTest.php index ad2f6f42e7..bacce9be1c 100644 --- a/tests/Unit/Integration/WPCOMProxyTest.php +++ b/tests/Unit/Integration/WPCOMProxyTest.php @@ -81,7 +81,7 @@ protected function add_metadata( int $id, array $meta ) { protected function maps_the_response_with_the_item_id( WP_REST_Response $response ): array { return array_reduce( $response->get_data(), - function( $c, $i ) { + function ( $c, $i ) { $c[ $i['id'] ] = $i; return $c; }, @@ -258,7 +258,6 @@ public function test_get_coupons() { $this->assertEquals( $coupon_1->get_id(), $response->get_data()[0]['id'] ); $this->assertEquals( $expected_metadata, $this->format_metadata( $response->get_data()[0]['meta_data'] ) ); - } public function test_get_coupons_with_customer_email_and_syncable() { @@ -352,7 +351,5 @@ public function test_get_coupons_without_gla_syncable_param() { $this->assertEquals( $this->get_test_metadata(), $this->format_metadata( $response_mapped[ $coupon_1->get_id() ]['meta_data'] ) ); $this->assertEquals( $this->get_test_metadata( 'dont-sync-and-show' ), $this->format_metadata( $response_mapped[ $coupon_2->get_id() ]['meta_data'] ) ); - } - } From 26f8c7bdfa1855805ad2c581c3d50040393dd1fb Mon Sep 17 00:00:00 2001 From: Jorge M Date: Mon, 13 Nov 2023 23:03:34 +0100 Subject: [PATCH 013/135] Rename post_types_to_filter --- src/Integration/WPCOMProxy.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Integration/WPCOMProxy.php b/src/Integration/WPCOMProxy.php index 9829d3cf43..e6acd57664 100644 --- a/src/Integration/WPCOMProxy.php +++ b/src/Integration/WPCOMProxy.php @@ -24,7 +24,7 @@ class WPCOMProxy implements Service, Registerable { * * @var array */ - public static $post_types_to_be_filter = [ + public static $post_types_to_filter = [ 'product' => [ 'meta_query' => [ [ @@ -65,7 +65,7 @@ function ( $valid_vars ) { } ); - foreach ( array_keys( self::$post_types_to_be_filter ) as $object_type ) { + foreach ( array_keys( self::$post_types_to_filter ) as $object_type ) { $this->register_object_types_filter( $object_type ); } } @@ -164,7 +164,7 @@ public function filter_by_metaquery( array $args, WP_REST_Request $request ): ar } $post_type = $args['post_type']; - $post_type_filters = self::$post_types_to_be_filter[ $post_type ]; + $post_type_filters = self::$post_types_to_filter[ $post_type ]; if ( ! isset( $post_type_filters['meta_query'] ) || ! is_array( $post_type_filters['meta_query'] ) ) { return $args; From 2a5d4b7bc544550eedcb9c1937770530822739b4 Mon Sep 17 00:00:00 2001 From: Jorge M Date: Mon, 13 Nov 2023 23:05:39 +0100 Subject: [PATCH 014/135] Tweak formatting --- src/Integration/WPCOMProxy.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Integration/WPCOMProxy.php b/src/Integration/WPCOMProxy.php index e6acd57664..c3fe26d3ac 100644 --- a/src/Integration/WPCOMProxy.php +++ b/src/Integration/WPCOMProxy.php @@ -76,7 +76,12 @@ function ( $valid_vars ) { * @param string $object_type The object type. */ protected function register_object_types_filter( string $object_type ): void { - add_filter( 'woocommerce_rest_prepare_' . $object_type . '_object', [ $this, 'check_item_is_syncable' ], 9, 3 ); + add_filter( + 'woocommerce_rest_prepare_' . $object_type . '_object', + [ $this, 'check_item_is_syncable' ], + 9, + 3 + ); add_filter( 'woocommerce_rest_prepare_' . $object_type . '_object', @@ -153,7 +158,7 @@ public function check_item_is_syncable( $response, $item, WP_REST_Request $reque /** * Query items with specific args for example where _wc_gla_visibility is set to sync-and-show. * - * @param array $args The query args. + * @param array $args The query args. * @param WP_REST_Request $request The request object. * * @return array The query args updated. From e78d7d072d371095263bf984c8c1818da5b9fa7f Mon Sep 17 00:00:00 2001 From: Jorge M Date: Mon, 13 Nov 2023 23:25:38 +0100 Subject: [PATCH 015/135] Check for the value of gla_syncable --- src/Integration/WPCOMProxy.php | 3 +- tests/Unit/Integration/WPCOMProxyTest.php | 41 +++++++++++++++++------ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/Integration/WPCOMProxy.php b/src/Integration/WPCOMProxy.php index c3fe26d3ac..4305df4eec 100644 --- a/src/Integration/WPCOMProxy.php +++ b/src/Integration/WPCOMProxy.php @@ -106,7 +106,8 @@ protected function register_object_types_filter( string $object_type ): void { * @return bool */ protected function should_filter_data( WP_REST_Request $request ): bool { - return $request->get_param( 'gla_syncable' ) !== null; + // WPCOM proxy will set the gla_syncable to 1 if the request is coming from the proxy and it is the Google App. + return $request->get_param( 'gla_syncable' ) === '1'; } /** diff --git a/tests/Unit/Integration/WPCOMProxyTest.php b/tests/Unit/Integration/WPCOMProxyTest.php index bacce9be1c..c64de5c385 100644 --- a/tests/Unit/Integration/WPCOMProxyTest.php +++ b/tests/Unit/Integration/WPCOMProxyTest.php @@ -96,7 +96,7 @@ public function test_get_products() { $this->add_metadata( $product_1->get_id(), $this->get_test_metadata() ); $this->add_metadata( $product_2->get_id(), $this->get_test_metadata( 'dont-sync-and-show' ) ); - $response = $this->do_request( '/wc/v3/products', 'GET', [ 'gla_syncable' => 1 ] ); + $response = $this->do_request( '/wc/v3/products', 'GET', [ 'gla_syncable' => '1' ] ); $this->assertEquals( 200, $response->get_status() ); $this->assertCount( 1, $response->get_data() ); @@ -110,6 +110,27 @@ public function test_get_products() { $this->assertEquals( $expected_metadata, $this->format_metadata( $response->get_data()[0]['meta_data'] ) ); } + public function test_get_products_with_gla_syncable_false() { + $product_1 = ProductHelper::create_simple_product(); + $product_2 = ProductHelper::create_simple_product(); + + $this->add_metadata( $product_1->get_id(), $this->get_test_metadata() ); + $this->add_metadata( $product_2->get_id(), $this->get_test_metadata( 'dont-sync-and-show' ) ); + + $response = $this->do_request( '/wc/v3/products', 'GET', [ 'gla_syncable' => '0' ] ); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertCount( 2, $response->get_data() ); + + $response_mapped = $this->maps_the_response_with_the_item_id( $response ); + + $this->assertArrayHasKey( $product_1->get_id(), $response_mapped ); + $this->assertArrayHasKey( $product_2->get_id(), $response_mapped ); + + $this->assertEquals( $this->get_test_metadata(), $this->format_metadata( $response_mapped[ $product_1->get_id() ]['meta_data'] ) ); + $this->assertEquals( $this->get_test_metadata( 'dont-sync-and-show' ), $this->format_metadata( $response_mapped[ $product_2->get_id() ]['meta_data'] ) ); + } + public function test_get_products_without_gla_visibility_metadata() { $product_1 = ProductHelper::create_simple_product(); $product_2 = ProductHelper::create_simple_product(); @@ -117,7 +138,7 @@ public function test_get_products_without_gla_visibility_metadata() { $this->add_metadata( $product_1->get_id(), $this->get_test_metadata( null ) ); $this->add_metadata( $product_2->get_id(), $this->get_test_metadata() ); - $response = $this->do_request( '/wc/v3/products', 'GET', [ 'gla_syncable' => 1 ] ); + $response = $this->do_request( '/wc/v3/products', 'GET', [ 'gla_syncable' => '1' ] ); $this->assertEquals( 200, $response->get_status() ); $this->assertCount( 1, $response->get_data() ); @@ -138,7 +159,7 @@ public function test_get_product_without_gla_visibility_metadata() { delete_post_meta( $product->get_id(), 'customer_email' ); - $response = $this->do_request( '/wc/v3/products/' . $product->get_id(), 'GET', [ 'gla_syncable' => 1 ] ); + $response = $this->do_request( '/wc/v3/products/' . $product->get_id(), 'GET', [ 'gla_syncable' => '1' ] ); $this->assertEquals( 403, $response->get_status() ); $this->assertEquals( 'gla_rest_item_no_syncable', $response->get_data()['code'] ); @@ -149,7 +170,7 @@ public function test_get_product_with_gla_visibility_metadata() { $product = ProductHelper::create_simple_product(); $this->add_metadata( $product->get_id(), $this->get_test_metadata() ); - $response = $this->do_request( '/wc/v3/products/' . $product->get_id(), 'GET', [ 'gla_syncable' => 1 ] ); + $response = $this->do_request( '/wc/v3/products/' . $product->get_id(), 'GET', [ 'gla_syncable' => '1' ] ); $this->assertEquals( 200, $response->get_status() ); $this->assertEquals( $product->get_id(), $response->get_data()['id'] ); @@ -195,7 +216,7 @@ public function test_get_variations() { $this->add_metadata( $variation['variation_id'], $this->get_test_metadata( null ) ); } - $response = $this->do_request( '/wc/v3/products/' . $product->get_id() . '/variations', 'GET', [ 'gla_syncable' => 1 ] ); + $response = $this->do_request( '/wc/v3/products/' . $product->get_id() . '/variations', 'GET', [ 'gla_syncable' => '1' ] ); $this->assertEquals( 200, $response->get_status() ); $this->assertCount( count( $variations ), $response->get_data() ); @@ -246,7 +267,7 @@ public function test_get_coupons() { delete_post_meta( $coupon_1->get_id(), 'customer_email' ); delete_post_meta( $coupon_2->get_id(), 'customer_email' ); - $response = $this->do_request( '/wc/v3/coupons', 'GET', [ 'gla_syncable' => 1 ] ); + $response = $this->do_request( '/wc/v3/coupons', 'GET', [ 'gla_syncable' => '1' ] ); $this->assertEquals( 200, $response->get_status() ); $this->assertCount( 1, $response->get_data() ); @@ -267,7 +288,7 @@ public function test_get_coupons_with_customer_email_and_syncable() { delete_post_meta( $coupon->get_id(), 'customer_email' ); - $response = $this->do_request( '/wc/v3/coupons', 'GET', [ 'gla_syncable' => 1 ] ); + $response = $this->do_request( '/wc/v3/coupons', 'GET', [ 'gla_syncable' => '1' ] ); $this->assertEquals( 200, $response->get_status() ); $this->assertCount( 1, $response->get_data() ); @@ -288,7 +309,7 @@ public function test_get_coupons_without_gla_visibility_metadata() { delete_post_meta( $coupon->get_id(), 'customer_email' ); - $response = $this->do_request( '/wc/v3/coupons', 'GET', [ 'gla_syncable' => 1 ] ); + $response = $this->do_request( '/wc/v3/coupons', 'GET', [ 'gla_syncable' => '1' ] ); $this->assertEquals( 200, $response->get_status() ); $this->assertCount( 1, $response->get_data() ); @@ -308,7 +329,7 @@ public function test_get_coupon_without_gla_visibility_metadata() { delete_post_meta( $coupon->get_id(), 'customer_email' ); - $response = $this->do_request( '/wc/v3/coupons/' . $coupon->get_id(), 'GET', [ 'gla_syncable' => 1 ] ); + $response = $this->do_request( '/wc/v3/coupons/' . $coupon->get_id(), 'GET', [ 'gla_syncable' => '1' ] ); $this->assertEquals( 403, $response->get_status() ); $this->assertEquals( 'gla_rest_item_no_syncable', $response->get_data()['code'] ); @@ -320,7 +341,7 @@ public function test_get_coupon_with_gla_visibility_metadata() { delete_post_meta( $coupon->get_id(), 'customer_email' ); - $response = $this->do_request( '/wc/v3/coupons/' . $coupon->get_id(), 'GET', [ 'gla_syncable' => 1 ] ); + $response = $this->do_request( '/wc/v3/coupons/' . $coupon->get_id(), 'GET', [ 'gla_syncable' => '1' ] ); $this->assertEquals( 200, $response->get_status() ); $this->assertEquals( $coupon->get_id(), $response->get_data()['id'] ); From 5ec640eed1f815a9e83cbfe0a4832b6e9627bce1 Mon Sep 17 00:00:00 2001 From: Jorge M Date: Tue, 14 Nov 2023 10:29:20 +0100 Subject: [PATCH 016/135] Tweaks filter function names and PHPDocs --- src/Integration/WPCOMProxy.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Integration/WPCOMProxy.php b/src/Integration/WPCOMProxy.php index 4305df4eec..82a7c2fb84 100644 --- a/src/Integration/WPCOMProxy.php +++ b/src/Integration/WPCOMProxy.php @@ -78,7 +78,7 @@ function ( $valid_vars ) { protected function register_object_types_filter( string $object_type ): void { add_filter( 'woocommerce_rest_prepare_' . $object_type . '_object', - [ $this, 'check_item_is_syncable' ], + [ $this, 'filter_response_by_syncable_item' ], 9, 3 ); @@ -111,7 +111,7 @@ protected function should_filter_data( WP_REST_Request $request ): bool { } /** - * Check if a single item is syncable. + * Filter response by syncable item. * * @param WP_REST_Response $response The response object. * @param mixed $item The item. @@ -119,7 +119,7 @@ protected function should_filter_data( WP_REST_Request $request ): bool { * * @return WP_REST_Response The response object updated. */ - public function check_item_is_syncable( $response, $item, WP_REST_Request $request ): WP_REST_Response { + public function filter_response_by_syncable_item( $response, $item, WP_REST_Request $request ): WP_REST_Response { if ( ! $this->should_filter_data( $request ) ) { return $response; } @@ -182,7 +182,7 @@ public function filter_by_metaquery( array $args, WP_REST_Request $request ): ar } /** - * Filter the metadata of an object. + * Filter the response metadata returning all public metadata and those prefixed with _wc_gla * * @param WP_REST_Response $response The response object. * @param mixed $item The item. @@ -207,7 +207,6 @@ public function filter_metadata( WP_REST_Response $response, $item, WP_REST_Requ } } - $data['meta_data'] = array_values( $data['meta_data'] ); $response->set_data( $data ); return $response; From b84999bfefe337177b41f5bd028c2bdc182042b5 Mon Sep 17 00:00:00 2001 From: Jorge M Date: Tue, 14 Nov 2023 11:09:21 +0100 Subject: [PATCH 017/135] Use the ChannelVisibility constants --- src/Integration/WPCOMProxy.php | 18 +++++++--- tests/Unit/Integration/WPCOMProxyTest.php | 40 ++++++++++++----------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/src/Integration/WPCOMProxy.php b/src/Integration/WPCOMProxy.php index 82a7c2fb84..89bd823596 100644 --- a/src/Integration/WPCOMProxy.php +++ b/src/Integration/WPCOMProxy.php @@ -5,6 +5,7 @@ use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Registerable; use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service; +use Automattic\WooCommerce\GoogleListingsAndAds\Value\ChannelVisibility; use WP_REST_Response; use WP_REST_Request; @@ -19,6 +20,13 @@ */ class WPCOMProxy implements Service, Registerable { + /** + * The meta key used to filter the items. + * + * @var string + */ + public const KEY_VISIBILITY = '_wc_gla_visibility'; + /** * The Post types to be filtered. * @@ -28,8 +36,8 @@ class WPCOMProxy implements Service, Registerable { 'product' => [ 'meta_query' => [ [ - 'key' => '_wc_gla_visibility', - 'value' => 'sync-and-show', + 'key' => self::KEY_VISIBILITY, + 'value' => ChannelVisibility::SYNC_AND_SHOW, 'compare' => '=', ], ], @@ -37,8 +45,8 @@ class WPCOMProxy implements Service, Registerable { 'shop_coupon' => [ 'meta_query' => [ [ - 'key' => '_wc_gla_visibility', - 'value' => 'sync-and-show', + 'key' => self::KEY_VISIBILITY, + 'value' => ChannelVisibility::SYNC_AND_SHOW, 'compare' => '=', ], [ @@ -139,7 +147,7 @@ public function filter_response_by_syncable_item( $response, $item, WP_REST_Requ $meta_data = $response->get_data()['meta_data'] ?? []; foreach ( $meta_data as $meta ) { - if ( $meta->key === '_wc_gla_visibility' && $meta->value === 'sync-and-show' ) { + if ( $meta->key === self::KEY_VISIBILITY && $meta->value === ChannelVisibility::SYNC_AND_SHOW ) { return $response; } } diff --git a/tests/Unit/Integration/WPCOMProxyTest.php b/tests/Unit/Integration/WPCOMProxyTest.php index c64de5c385..ec548572bb 100644 --- a/tests/Unit/Integration/WPCOMProxyTest.php +++ b/tests/Unit/Integration/WPCOMProxyTest.php @@ -5,6 +5,8 @@ use Automattic\WooCommerce\RestApi\UnitTests\Helpers\CouponHelper; use Automattic\WooCommerce\RestApi\UnitTests\Helpers\ProductHelper; use Automattic\WooCommerce\GoogleListingsAndAds\Tests\Framework\RESTControllerUnitTest; +use Automattic\WooCommerce\GoogleListingsAndAds\Value\ChannelVisibility; +use Automattic\WooCommerce\GoogleListingsAndAds\Integration\WPCOMProxy; use WC_Meta_Data; use WP_REST_Response; @@ -46,14 +48,14 @@ protected function format_metadata( array $metadata ): array { * * @return array */ - protected function get_test_metadata( $visibility = 'sync-and-show' ): array { + protected function get_test_metadata( $visibility = ChannelVisibility::SYNC_AND_SHOW ): array { $args = [ '_private_meta' => 'private', 'public_meta' => 'public', ]; if ( $visibility ) { - $args['_wc_gla_visibility'] = $visibility; + $args[ WPCOMProxy::KEY_VISIBILITY ] = $visibility; } return $args; } @@ -94,7 +96,7 @@ public function test_get_products() { $product_2 = ProductHelper::create_simple_product(); $this->add_metadata( $product_1->get_id(), $this->get_test_metadata() ); - $this->add_metadata( $product_2->get_id(), $this->get_test_metadata( 'dont-sync-and-show' ) ); + $this->add_metadata( $product_2->get_id(), $this->get_test_metadata( ChannelVisibility::DONT_SYNC_AND_SHOW ) ); $response = $this->do_request( '/wc/v3/products', 'GET', [ 'gla_syncable' => '1' ] ); @@ -102,8 +104,8 @@ public function test_get_products() { $this->assertCount( 1, $response->get_data() ); $expected_metadata = [ - 'public_meta' => 'public', - '_wc_gla_visibility' => 'sync-and-show', + 'public_meta' => 'public', + WPCOMProxy::KEY_VISIBILITY => ChannelVisibility::SYNC_AND_SHOW, ]; $this->assertEquals( $product_1->get_id(), $response->get_data()[0]['id'] ); @@ -115,7 +117,7 @@ public function test_get_products_with_gla_syncable_false() { $product_2 = ProductHelper::create_simple_product(); $this->add_metadata( $product_1->get_id(), $this->get_test_metadata() ); - $this->add_metadata( $product_2->get_id(), $this->get_test_metadata( 'dont-sync-and-show' ) ); + $this->add_metadata( $product_2->get_id(), $this->get_test_metadata( ChannelVisibility::DONT_SYNC_AND_SHOW ) ); $response = $this->do_request( '/wc/v3/products', 'GET', [ 'gla_syncable' => '0' ] ); @@ -128,7 +130,7 @@ public function test_get_products_with_gla_syncable_false() { $this->assertArrayHasKey( $product_2->get_id(), $response_mapped ); $this->assertEquals( $this->get_test_metadata(), $this->format_metadata( $response_mapped[ $product_1->get_id() ]['meta_data'] ) ); - $this->assertEquals( $this->get_test_metadata( 'dont-sync-and-show' ), $this->format_metadata( $response_mapped[ $product_2->get_id() ]['meta_data'] ) ); + $this->assertEquals( $this->get_test_metadata( ChannelVisibility::DONT_SYNC_AND_SHOW ), $this->format_metadata( $response_mapped[ $product_2->get_id() ]['meta_data'] ) ); } public function test_get_products_without_gla_visibility_metadata() { @@ -144,8 +146,8 @@ public function test_get_products_without_gla_visibility_metadata() { $this->assertCount( 1, $response->get_data() ); $expected_metadata = [ - 'public_meta' => 'public', - '_wc_gla_visibility' => 'sync-and-show', + 'public_meta' => 'public', + WPCOMProxy::KEY_VISIBILITY => ChannelVisibility::SYNC_AND_SHOW, ]; $this->assertEquals( $product_2->get_id(), $response->get_data()[0]['id'] ); @@ -191,7 +193,7 @@ public function test_get_products_without_gla_syncable_param() { $product_1 = ProductHelper::create_simple_product(); $product_2 = ProductHelper::create_simple_product(); $this->add_metadata( $product_1->get_id(), $this->get_test_metadata() ); - $this->add_metadata( $product_2->get_id(), $this->get_test_metadata( 'dont-sync-and-show' ) ); + $this->add_metadata( $product_2->get_id(), $this->get_test_metadata( ChannelVisibility::DONT_SYNC_AND_SHOW ) ); $response = $this->do_request( '/wc/v3/products', 'GET' ); @@ -204,7 +206,7 @@ public function test_get_products_without_gla_syncable_param() { $this->assertArrayHasKey( $product_2->get_id(), $response_mapped ); $this->assertEquals( $this->get_test_metadata(), $this->format_metadata( $response_mapped[ $product_1->get_id() ]['meta_data'] ) ); - $this->assertEquals( $this->get_test_metadata( 'dont-sync-and-show' ), $this->format_metadata( $response_mapped[ $product_2->get_id() ]['meta_data'] ) ); + $this->assertEquals( $this->get_test_metadata( ChannelVisibility::DONT_SYNC_AND_SHOW ), $this->format_metadata( $response_mapped[ $product_2->get_id() ]['meta_data'] ) ); } public function test_get_variations() { @@ -262,7 +264,7 @@ public function test_get_variations_without_gla_syncable_param() { public function test_get_coupons() { $coupon_1 = CouponHelper::create_coupon( 'dummycoupon-1', 'publish', $this->get_test_metadata() ); - $coupon_2 = CouponHelper::create_coupon( 'dummycoupon-2', 'publish', $this->get_test_metadata( 'dont-sync-and-show' ) ); + $coupon_2 = CouponHelper::create_coupon( 'dummycoupon-2', 'publish', $this->get_test_metadata( ChannelVisibility::DONT_SYNC_AND_SHOW ) ); delete_post_meta( $coupon_1->get_id(), 'customer_email' ); delete_post_meta( $coupon_2->get_id(), 'customer_email' ); @@ -273,8 +275,8 @@ public function test_get_coupons() { $this->assertCount( 1, $response->get_data() ); $expected_metadata = [ - 'public_meta' => 'public', - '_wc_gla_visibility' => 'sync-and-show', + 'public_meta' => 'public', + WPCOMProxy::KEY_VISIBILITY => ChannelVisibility::SYNC_AND_SHOW, ]; $this->assertEquals( $coupon_1->get_id(), $response->get_data()[0]['id'] ); @@ -294,8 +296,8 @@ public function test_get_coupons_with_customer_email_and_syncable() { $this->assertCount( 1, $response->get_data() ); $expected_metadata = [ - 'public_meta' => 'public', - '_wc_gla_visibility' => 'sync-and-show', + 'public_meta' => 'public', + WPCOMProxy::KEY_VISIBILITY => ChannelVisibility::SYNC_AND_SHOW, ]; $this->assertEquals( $coupon->get_id(), $response->get_data()[0]['id'] ); @@ -315,8 +317,8 @@ public function test_get_coupons_without_gla_visibility_metadata() { $this->assertCount( 1, $response->get_data() ); $expected_metadata = [ - 'public_meta' => 'public', - '_wc_gla_visibility' => 'sync-and-show', + 'public_meta' => 'public', + WPCOMProxy::KEY_VISIBILITY => ChannelVisibility::SYNC_AND_SHOW, ]; $this->assertEquals( $coupon->get_id(), $response->get_data()[0]['id'] ); @@ -358,7 +360,7 @@ public function test_get_coupon_without_gla_syncable_param() { public function test_get_coupons_without_gla_syncable_param() { $coupon_1 = CouponHelper::create_coupon( 'dummycoupon-1', 'publish', $this->get_test_metadata() ); - $coupon_2 = CouponHelper::create_coupon( 'dummycoupon-2', 'publish', $this->get_test_metadata( 'dont-sync-and-show' ) ); + $coupon_2 = CouponHelper::create_coupon( 'dummycoupon-2', 'publish', $this->get_test_metadata( ChannelVisibility::DONT_SYNC_AND_SHOW ) ); $response = $this->do_request( '/wc/v3/coupons', 'GET' ); From f673381adc4b06444927b67d9dfeb8ad4580ce28 Mon Sep 17 00:00:00 2001 From: Miguel Perez Pellicer <5908855+puntope@users.noreply.github.com> Date: Wed, 27 Dec 2023 17:17:03 -0500 Subject: [PATCH 018/135] Create NotificationsService --- src/Google/NotificationsService.php | 114 ++++++++++++++++++ .../CoreServiceProvider.php | 6 + .../JobServiceProvider.php | 2 + 3 files changed, 122 insertions(+) create mode 100644 src/Google/NotificationsService.php diff --git a/src/Google/NotificationsService.php b/src/Google/NotificationsService.php new file mode 100644 index 0000000000..e1b8df29d6 --- /dev/null +++ b/src/Google/NotificationsService.php @@ -0,0 +1,114 @@ +route = "https://public-api.wordpress.com/wpcom/v2/sites/{$blog_id}/partners/google/notifications"; + } + + /** + * Calls the Notification endpoint in WPCOM. + * https://public-api.wordpress.com/wpcom/v2/sites/{site}/partners/google/notifications + * + * @param int $item_id + * @param string $topic + * @return bool True is the notification is successful. False otherwise. + */ + public function notify( int $item_id, string $topic ) { + $remote_args = [ + 'method' => 'POST', + 'timeout' => 30, + 'headers' => [ + 'x-woocommerce-topic' => $topic, + ], + 'body' => [ + 'item_id' => $item_id, + ], + 'url' => $this->get_route(), + ]; + + $response = $this->do_request( $remote_args ); + + if ( is_wp_error( $response ) ) { + $this->notification_error( $item_id, $topic, $response->get_error_message() ); + return false; + } + + if ( wp_remote_retrieve_response_code( $response ) >= 400 ) { + $this->notification_error( $item_id, $topic, wp_remote_retrieve_body( $response ) ); + return false; + } + + return true; + } + + /** + * Logs an error. + * + * @param int $item_id + * @param string $topic + * @param string $error + */ + private function notification_error( int $item_id, string $topic, string $error ): void { + do_action( + 'woocommerce_gla_error', + sprintf( 'Error sending notification for Item ID %d with topic %s. %s', $item_id, $topic, $error ), + __METHOD__ + ); + } + + /** + * Performs a Remote Request + * + * @param array $args + * @return array|\WP_Error + */ + protected function do_request( $args ) { + return Client::remote_request( $args, wp_json_encode( $args['body'] ) ); + } + + /** + * Get the route + * + * @return string The route. + */ + public function get_route(): string { + return $this->route; + } +} diff --git a/src/Internal/DependencyManagement/CoreServiceProvider.php b/src/Internal/DependencyManagement/CoreServiceProvider.php index ab8a3009e3..e35c5f9ea0 100644 --- a/src/Internal/DependencyManagement/CoreServiceProvider.php +++ b/src/Internal/DependencyManagement/CoreServiceProvider.php @@ -42,6 +42,7 @@ use Automattic\WooCommerce\GoogleListingsAndAds\Google\GoogleHelperAwareInterface; use Automattic\WooCommerce\GoogleListingsAndAds\Google\GoogleProductService; use Automattic\WooCommerce\GoogleListingsAndAds\Google\GooglePromotionService; +use Automattic\WooCommerce\GoogleListingsAndAds\Google\NotificationsService; use Automattic\WooCommerce\GoogleListingsAndAds\Google\RequestReviewStatuses; use Automattic\WooCommerce\GoogleListingsAndAds\Google\SiteVerificationMeta; use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service; @@ -191,6 +192,7 @@ class CoreServiceProvider extends AbstractServiceProvider { PolicyComplianceCheck::class => true, ContactInformation::class => true, MerchantCenterService::class => true, + NotificationsService::class => true, TargetAudience::class => true, MerchantAccountState::class => true, AdsAccountState::class => true, @@ -245,6 +247,10 @@ public function register(): void { // Set up MerchantCenter service, and inflect classes that need it. $this->share_with_tags( MerchantCenterService::class ); + + // Set up Notifications service. + $this->share_with_tags( NotificationsService::class ); + $this->getLeagueContainer() ->inflector( MerchantCenterAwareInterface::class ) ->invokeMethod( 'set_merchant_center_object', [ MerchantCenterService::class ] ); diff --git a/src/Internal/DependencyManagement/JobServiceProvider.php b/src/Internal/DependencyManagement/JobServiceProvider.php index 2ad3cbe7ec..d4c9571aa0 100644 --- a/src/Internal/DependencyManagement/JobServiceProvider.php +++ b/src/Internal/DependencyManagement/JobServiceProvider.php @@ -11,6 +11,7 @@ use Automattic\WooCommerce\GoogleListingsAndAds\API\Google\Settings as GoogleSettings; use Automattic\WooCommerce\GoogleListingsAndAds\Exception\InvalidClass; use Automattic\WooCommerce\GoogleListingsAndAds\Exception\ValidateInterface; +use Automattic\WooCommerce\GoogleListingsAndAds\Google\NotificationsService; use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service; use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\AbstractProductSyncerBatchedJob; use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\ActionSchedulerJobInterface; @@ -121,6 +122,7 @@ public function register(): void { ProductHelper::class, JobRepository::class, MerchantCenterService::class, + NotificationsService::class, WC::class ); From 897e2d1d7d3a2b60ba37a8ae226fd1c7252ea390 Mon Sep 17 00:00:00 2001 From: Miguel Perez Pellicer <5908855+puntope@users.noreply.github.com> Date: Wed, 27 Dec 2023 17:17:22 -0500 Subject: [PATCH 019/135] Call Notify on Product changes --- src/Product/SyncerHooks.php | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/Product/SyncerHooks.php b/src/Product/SyncerHooks.php index 0d7cc0c112..729f593f3a 100644 --- a/src/Product/SyncerHooks.php +++ b/src/Product/SyncerHooks.php @@ -4,6 +4,7 @@ namespace Automattic\WooCommerce\GoogleListingsAndAds\Product; use Automattic\WooCommerce\GoogleListingsAndAds\Google\BatchProductIDRequestEntry; +use Automattic\WooCommerce\GoogleListingsAndAds\Google\NotificationsService; use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Registerable; use Automattic\WooCommerce\GoogleListingsAndAds\Infrastructure\Service; use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\DeleteProducts; @@ -70,6 +71,11 @@ class SyncerHooks implements Service, Registerable { */ protected $merchant_center; + /** + * @var NotificationsService + */ + protected $notifications_service; + /** * @var WC */ @@ -82,6 +88,7 @@ class SyncerHooks implements Service, Registerable { * @param ProductHelper $product_helper * @param JobRepository $job_repository * @param MerchantCenterService $merchant_center + * @param NotificationsService $notifications_service * @param WC $wc */ public function __construct( @@ -89,14 +96,16 @@ public function __construct( ProductHelper $product_helper, JobRepository $job_repository, MerchantCenterService $merchant_center, + NotificationsService $notifications_service, WC $wc ) { - $this->batch_helper = $batch_helper; - $this->product_helper = $product_helper; - $this->update_products_job = $job_repository->get( UpdateProducts::class ); - $this->delete_products_job = $job_repository->get( DeleteProducts::class ); - $this->merchant_center = $merchant_center; - $this->wc = $wc; + $this->batch_helper = $batch_helper; + $this->product_helper = $product_helper; + $this->update_products_job = $job_repository->get( UpdateProducts::class ); + $this->delete_products_job = $job_repository->get( DeleteProducts::class ); + $this->merchant_center = $merchant_center; + $this->notifications_service = $notifications_service; + $this->wc = $wc; } /** @@ -104,17 +113,20 @@ public function __construct( */ public function register(): void { // only register the hooks if Merchant Center is connected and ready for syncing data. + // TODO: Potentially change this after API Pull is implemented as we don't need MC to be connected for the API Pull if ( ! $this->merchant_center->is_ready_for_syncing() ) { return; } $update_by_object = function ( int $product_id, WC_Product $product ) { + $this->notifications_service->notify( $product_id, $this->notifications_service::TOPIC_PRODUCT_UPDATED ); $this->handle_update_products( [ $product ] ); }; $update_by_id = function ( int $product_id ) { $product = $this->wc->maybe_get_product( $product_id ); if ( $product instanceof WC_Product ) { + $this->notifications_service->notify( $product_id, $this->notifications_service::TOPIC_PRODUCT_CREATED ); $this->handle_update_products( [ $product ] ); } }; @@ -142,8 +154,6 @@ public function register(): void { add_action( 'woocommerce_before_delete_product_variation', $pre_delete, 90 ); add_action( 'trashed_post', $delete, 90 ); add_action( 'deleted_post', $delete, 90 ); - add_action( 'woocommerce_delete_product_variation', $delete, 90 ); - add_action( 'woocommerce_trash_product_variation', $delete, 90 ); // when a product is restored from the trash, schedule an "update" job. add_action( 'untrashed_post', $update_by_id, 90 ); @@ -219,6 +229,11 @@ protected function handle_update_products( array $products ) { * @param int $product_id */ protected function handle_delete_product( int $product_id ) { + $product = wc_get_product( $product_id ); + if ( $product instanceof WC_Product ) { + $this->notifications_service->notify( $product_id, $this->notifications_service::TOPIC_PRODUCT_DELETED ); + } + if ( isset( $this->delete_requests_map[ $product_id ] ) ) { $product_id_map = BatchProductIDRequestEntry::convert_to_id_map( $this->delete_requests_map[ $product_id ] )->get(); if ( ! empty( $product_id_map ) && ! $this->is_already_scheduled_to_delete( $product_id ) ) { From 8587db5d1cb6e266c373f2bb84a4adb2ad86beb8 Mon Sep 17 00:00:00 2001 From: Miguel Perez Pellicer <5908855+puntope@users.noreply.github.com> Date: Wed, 27 Dec 2023 17:17:37 -0500 Subject: [PATCH 020/135] Update tests --- .../Unit/Google/NotificationsServiceTest.php | 102 ++++++++++++++++++ tests/Unit/Product/SyncerHooksTest.php | 84 +++++++++++---- 2 files changed, 168 insertions(+), 18 deletions(-) create mode 100644 tests/Unit/Google/NotificationsServiceTest.php diff --git a/tests/Unit/Google/NotificationsServiceTest.php b/tests/Unit/Google/NotificationsServiceTest.php new file mode 100644 index 0000000000..a577364743 --- /dev/null +++ b/tests/Unit/Google/NotificationsServiceTest.php @@ -0,0 +1,102 @@ +service = $this->get_mock(); + } + + /** + * Test if the route is correct + */ + public function test_route() { + $blog_id = self::DUMMY_BLOG_ID; + $this->assertEquals( $this->service->get_route(), "https://public-api.wordpress.com/wpcom/v2/sites/{$blog_id}/partners/google/notifications" ); + } + + /** + * Test notify() function with a call with success response. + */ + public function test_notify() { + $topic = 'topic'; + $item_id = 1; + + $args = [ + 'method' => 'POST', + 'timeout' => 30, + 'headers' => [ + 'x-woocommerce-topic' => $topic + ], + 'body' => [ + 'item_id' => $item_id, + ], + 'url' => $this->service->get_route(), + ]; + + $this->service->expects( $this->once() )->method( 'do_request' )->with( $args )->willReturn( [ 'code' => 200 ] ); + $this->assertTrue( $this->service->notify( $item_id , $topic ) ); + } + + /** + * Test notify() function with a call with wp_error response. + */ + public function test_notify_wp_error() { + $this->service->expects( $this->once() )->method( 'do_request' )->willReturn( new \WP_Error( 'error', 'error message' ) ); + $this->assertFalse( $this->service->notify( 1 , 'topic') ); + $this->assertEquals( did_action( 'woocommerce_gla_error' ), 1 ); + } + + /** + * Test notify() function with a call with an error response. + */ + public function test_notify_response_error() { + $this->service->expects( $this->once() )->method( 'do_request' )->willReturn( [ 'response' => [ 'code' => 400, 'body' => 'Bad request' ] ] ); + $this->assertFalse( $this->service->notify( 1 , 'topic') ); + $this->assertEquals( did_action( 'woocommerce_gla_error' ), 1 ); + } + + /** + * Mocks the service + * @return NotificationsService + */ + public function get_mock() { + return $this->getMockBuilder( NotificationsService::class) + ->setMethods( [ 'do_request' ] ) + ->getMock(); + } + + } diff --git a/tests/Unit/Product/SyncerHooksTest.php b/tests/Unit/Product/SyncerHooksTest.php index be6523bf5b..95265cb96d 100644 --- a/tests/Unit/Product/SyncerHooksTest.php +++ b/tests/Unit/Product/SyncerHooksTest.php @@ -3,6 +3,7 @@ namespace Automattic\WooCommerce\GoogleListingsAndAds\Tests\Unit\Product; +use Automattic\WooCommerce\GoogleListingsAndAds\Google\NotificationsService; use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\DeleteProducts; use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\JobRepository; use Automattic\WooCommerce\GoogleListingsAndAds\Jobs\UpdateProducts; @@ -43,26 +44,37 @@ class SyncerHooksTest extends ContainerAwareUnitTest { /** @var MockObject|DeleteProducts $delete_products_job */ protected $delete_products_job; + /** + * @var MockObject|NotificationsService + */ + protected $notification_service; + /** @var WC $wc */ protected $wc; /** @var SyncerHooks $syncer_hooks */ protected $syncer_hooks; - public function test_create_new_simple_product_schedules_update_job() { + public function test_create_new_simple_product_schedules_update_job_and_calls_notify() { $this->update_products_job->expects( $this->once() ) ->method( 'schedule' ); + $this->notification_service->expects( $this->once() )->method( 'notify' )->with( $this->isType('int'), NotificationsService::TOPIC_PRODUCT_CREATED ); + + WC_Helper_Product::create_simple_product( true, [ 'status' => 'publish' ] ); } - public function test_update_simple_product_schedules_update_job() { + public function test_update_simple_product_schedules_update_job_and_calls_notify() { $product = WC_Helper_Product::create_simple_product( true, [ 'status' => 'draft' ] ); $this->update_products_job->expects( $this->once() ) ->method( 'schedule' ) ->with( $this->equalTo( [ [ $product->get_id() ] ] ) ); + $this->notification_service->expects( $this->once() ) + ->method( 'notify' )->with( $product->get_id(), NotificationsService::TOPIC_PRODUCT_UPDATED ); + $product->set_status( 'publish' ); $product->save(); } @@ -95,12 +107,15 @@ public function test_create_variable_product_schedules_update_job_for_all_variat $variable_product->save(); } - public function test_adding_variation_schedules_update_job() { + public function test_adding_variation_schedules_update_job_and_calls_notify() { $variable_product = $this->create_variation_product(); $this->update_products_job->expects( $this->once() ) ->method( 'schedule' ); + $this->notification_service->expects( $this->once() ) + ->method( 'notify' )->with( $this->isType('int'), NotificationsService::TOPIC_PRODUCT_CREATED ); + $this->create_product_variation_object( $variable_product->get_id(), 'DUMMY SKU VARIABLE SMALL BLUE 2', @@ -123,7 +138,7 @@ public function test_trashing_product_does_not_schedules_delete_job_if_product_i $product->delete(); } - public function test_trashing_synced_product_schedules_delete_job() { + public function test_trashing_synced_product_schedules_delete_job_and_calls_notify() { $product = WC_Helper_Product::create_simple_product(); $this->product_helper->mark_as_synced( $product, $this->generate_google_product_mock( 'online:en:US:gla_1' ) ); @@ -131,10 +146,14 @@ public function test_trashing_synced_product_schedules_delete_job() { ->method( 'schedule' ) ->with( $this->equalTo( [ [ 'online:en:US:gla_1' => $product->get_id() ] ] ) ); + $this->notification_service->expects( $this->once() ) + ->method( 'notify' ) + ->with( $product->get_id(), NotificationsService::TOPIC_PRODUCT_DELETED ); + $product->delete(); } - public function test_force_deleting_synced_product_schedules_delete_job() { + public function test_force_deleting_synced_product_schedules_delete_job_and_calls_notify() { $product = WC_Helper_Product::create_simple_product(); $this->product_helper->mark_as_synced( $product, $this->generate_google_product_mock( 'online:en:US:gla_1' ) ); @@ -142,6 +161,10 @@ public function test_force_deleting_synced_product_schedules_delete_job() { ->method( 'schedule' ) ->with( $this->equalTo( [ [ 'online:en:US:gla_1' => $product->get_id() ] ] ) ); + $this->notification_service->expects( $this->once() ) + ->method( 'notify' ) + ->with( $product->get_id(), NotificationsService::TOPIC_PRODUCT_DELETED ); + $product->delete( true ); } @@ -171,7 +194,7 @@ public function test_force_deleting_synced_variable_schedules_delete_job_for_all $variable_product->delete( true ); } - public function test_trashing_synced_variation_schedules_delete_job() { + public function test_trashing_synced_variation_schedules_delete_job_and_calls_notify() { $variable_product = $this->create_variation_product(); foreach ( $variable_product->get_children() as $variation_id ) { $variation = wc_get_product( $variation_id ); @@ -183,10 +206,15 @@ public function test_trashing_synced_variation_schedules_delete_job() { ->method( 'schedule' ) ->with( $this->equalTo( [ [ 'online:en:US:gla_' . $variation_to_delete->get_id() => $variation_to_delete->get_id() ] ] ) ); + $this->notification_service->expects( $this->once() ) + ->method( 'notify' ) + ->with( $variation_to_delete->get_id(), NotificationsService::TOPIC_PRODUCT_DELETED ); + $variation_to_delete->delete(); } - public function test_force_deleting_synced_variation_schedules_delete_job() { + + public function test_force_deleting_synced_variation_schedules_delete_job_and_calls_notify() { $variable_product = $this->create_variation_product(); foreach ( $variable_product->get_children() as $variation_id ) { $variation = wc_get_product( $variation_id ); @@ -198,6 +226,10 @@ public function test_force_deleting_synced_variation_schedules_delete_job() { ->method( 'schedule' ) ->with( $this->equalTo( [ [ 'online:en:US:gla_' . $variation_to_delete->get_id() => $variation_to_delete->get_id() ] ] ) ); + $this->notification_service->expects( $this->once() ) + ->method( 'notify' ) + ->with( $variation_to_delete->get_id(), NotificationsService::TOPIC_PRODUCT_DELETED ); + $variation_to_delete->delete( true ); } @@ -212,7 +244,7 @@ public function test_saving_synced_but_not_sync_ready_product_schedules_delete_j $product->save(); } - public function test_trashing_synced_product_wp_post_schedules_delete_job() { + public function test_trashing_synced_product_wp_post_schedules_delete_job_and_calls_notify() { $product = WC_Helper_Product::create_simple_product(); $this->product_helper->mark_as_synced( $product, $this->generate_google_product_mock( 'online:en:US:gla_1' ) ); @@ -220,10 +252,14 @@ public function test_trashing_synced_product_wp_post_schedules_delete_job() { ->method( 'schedule' ) ->with( $this->equalTo( [ [ 'online:en:US:gla_1' => $product->get_id() ] ] ) ); + $this->notification_service->expects( $this->once() ) + ->method( 'notify' ) + ->with( $product->get_id(), NotificationsService::TOPIC_PRODUCT_DELETED ); + wp_trash_post( $product->get_id() ); } - public function test_force_deleting_synced_product_wp_post_schedules_delete_job() { + public function test_force_deleting_synced_product_wp_post_schedules_delete_job_and_calls_notify() { $product = WC_Helper_Product::create_simple_product(); $this->product_helper->mark_as_synced( $product, $this->generate_google_product_mock( 'online:en:US:gla_1' ) ); @@ -231,13 +267,20 @@ public function test_force_deleting_synced_product_wp_post_schedules_delete_job( ->method( 'schedule' ) ->with( $this->equalTo( [ [ 'online:en:US:gla_1' => $product->get_id() ] ] ) ); + $this->notification_service->expects( $this->once() ) + ->method( 'notify' ) + ->with( $product->get_id(), NotificationsService::TOPIC_PRODUCT_DELETED ); + wp_delete_post( $product->get_id(), true ); } - public function test_creating_and_updating_post_does_not_schedule_update_job() { + public function test_creating_and_updating_post_does_not_schedule_update_job_either_notify() { $this->update_products_job->expects( $this->never() ) ->method( 'schedule' ); + $this->notification_service->expects( $this->never() ) + ->method( 'notify' ); + $post = $this->factory()->post->create_and_get(); // update post @@ -250,10 +293,13 @@ public function test_creating_and_updating_post_does_not_schedule_update_job() { wp_untrash_post( $post->ID ); } - public function test_trashing_and_deleting_post_does_not_schedule_delete_job() { + public function test_trashing_and_deleting_post_does_not_schedule_delete_job_either_notify() { $this->delete_products_job->expects( $this->never() ) ->method( 'schedule' ); + $this->notification_service->expects( $this->never() ) + ->method( 'notify' ); + $post = $this->factory()->post->create_and_get(); // trash post @@ -276,9 +322,11 @@ public function setUp(): void { ->method( 'is_ready_for_syncing' ) ->willReturn( true ); - $this->update_products_job = $this->createMock( UpdateProducts::class ); - $this->delete_products_job = $this->createMock( DeleteProducts::class ); - $this->job_repository = $this->createMock( JobRepository::class ); + $this->update_products_job = $this->createMock( UpdateProducts::class ); + $this->delete_products_job = $this->createMock( DeleteProducts::class ); + $this->job_repository = $this->createMock( JobRepository::class ); + $this->notification_service = $this->createMock( NotificationsService::class ); + $this->job_repository->expects( $this->any() ) ->method( 'get' ) ->willReturnMap( @@ -288,10 +336,10 @@ public function setUp(): void { ] ); - $this->batch_helper = $this->container->get( BatchProductHelper::class ); - $this->product_helper = $this->container->get( ProductHelper::class ); - $this->wc = $this->container->get( WC::class ); - $this->syncer_hooks = new SyncerHooks( $this->batch_helper, $this->product_helper, $this->job_repository, $this->merchant_center, $this->wc ); + $this->batch_helper = $this->container->get( BatchProductHelper::class ); + $this->product_helper = $this->container->get( ProductHelper::class ); + $this->wc = $this->container->get( WC::class ); + $this->syncer_hooks = new SyncerHooks( $this->batch_helper, $this->product_helper, $this->job_repository, $this->merchant_center, $this->notification_service, $this->wc ); $this->syncer_hooks->register(); } From 80c27f00957c56149bbea1223b8594df65420108 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 12:29:25 +0000 Subject: [PATCH 021/135] Start `release/2.5.13`. From ca4e35a037098f1b0486857f55157c36d287257b Mon Sep 17 00:00:00 2001 From: Martyn Jones Date: Wed, 6 Dec 2023 12:34:18 +0000 Subject: [PATCH 022/135] Update readme.txt --- readme.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/readme.txt b/readme.txt index e4d3741267..a9fa253810 100644 --- a/readme.txt +++ b/readme.txt @@ -125,8 +125,4 @@ Yes, you can run both at the same time, and we recommend it! In the US, advertis * Tweak - WP 6.4 compatibility. * Update - Use new Woo.com domain. -= 2.5.10 - 2023-10-18 = -* Tweak - Add correct Destinations for Supported Countries in Coupons. -* Tweak - Declare cart_checkout_blocks feature compatibility. - [See changelog for all versions](https://raw.githubusercontent.com/woocommerce/google-listings-and-ads/trunk/changelog.txt). From caa952a1f0f454fab26426e195916dd69f52b845 Mon Sep 17 00:00:00 2001 From: Martyn Jones Date: Wed, 6 Dec 2023 12:41:02 +0000 Subject: [PATCH 023/135] Set migration version number --- src/DB/Migration/Migration20231109T1653383133.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DB/Migration/Migration20231109T1653383133.php b/src/DB/Migration/Migration20231109T1653383133.php index e6ef94e79b..83582b2603 100644 --- a/src/DB/Migration/Migration20231109T1653383133.php +++ b/src/DB/Migration/Migration20231109T1653383133.php @@ -41,7 +41,7 @@ public function __construct( \wpdb $wpdb, BudgetRecommendationTable $budget_rate * @return string A version number. For example: 1.4.1 */ public function get_applicable_version(): string { - return 'x.x.x'; + return '2.5.13'; } /** From 704efb7386c5292f38bcb7a3178be6e3dbf84a6e Mon Sep 17 00:00:00 2001 From: Martyn Jones Date: Wed, 6 Dec 2023 12:53:58 +0000 Subject: [PATCH 024/135] Product version bump update --- google-listings-and-ads.php | 4 ++-- package-lock.json | 2 +- package.json | 2 +- readme.txt | 2 +- src/DB/Migration/Migration20231109T1653383133.php | 2 +- src/DB/Table.php | 2 +- src/DB/TableInterface.php | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/google-listings-and-ads.php b/google-listings-and-ads.php index 2f1bcd1276..e6cf827cc6 100644 --- a/google-listings-and-ads.php +++ b/google-listings-and-ads.php @@ -3,7 +3,7 @@ * Plugin Name: Google Listings and Ads * Plugin URL: https://wordpress.org/plugins/google-listings-and-ads/ * Description: Native integration with Google that allows merchants to easily display their products across Google’s network. - * Version: 2.5.12 + * Version: 2.5.13 * Author: WooCommerce * Author URI: https://woo.com/ * Text Domain: google-listings-and-ads @@ -30,7 +30,7 @@ defined( 'ABSPATH' ) || exit; -define( 'WC_GLA_VERSION', '2.5.12' ); // WRCS: DEFINED_VERSION. +define( 'WC_GLA_VERSION', '2.5.13' ); // WRCS: DEFINED_VERSION. define( 'WC_GLA_MIN_PHP_VER', '7.4' ); define( 'WC_GLA_MIN_WC_VER', '6.9' ); diff --git a/package-lock.json b/package-lock.json index fac19e403e..9e77836e99 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "google-listings-and-ads", - "version": "2.5.12", + "version": "2.5.13", "lockfileVersion": 2, "requires": true, "packages": { diff --git a/package.json b/package.json index 7aef4bccb8..76b8f248c9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "google-listings-and-ads", "title": "Google Listings and Ads", - "version": "2.5.12", + "version": "2.5.13", "description": "google-listings-and-ads", "author": "Automattic", "license": "GPL-3.0-or-later", diff --git a/readme.txt b/readme.txt index a9fa253810..c41187bfb9 100644 --- a/readme.txt +++ b/readme.txt @@ -5,7 +5,7 @@ Requires at least: 5.9 Tested up to: 6.4 Requires PHP: 7.4 Requires PHP Architecture: 64 Bits -Stable tag: 2.5.12 +Stable tag: 2.5.13 License: GPLv3 License URI: https://www.gnu.org/licenses/gpl-3.0.html diff --git a/src/DB/Migration/Migration20231109T1653383133.php b/src/DB/Migration/Migration20231109T1653383133.php index 83582b2603..bb82d87ea0 100644 --- a/src/DB/Migration/Migration20231109T1653383133.php +++ b/src/DB/Migration/Migration20231109T1653383133.php @@ -14,7 +14,7 @@ * * @package Automattic\WooCommerce\GoogleListingsAndAds\DB\Migration * - * @since x.x.x + * @since 2.5.13 */ class Migration20231109T1653383133 extends AbstractMigration { diff --git a/src/DB/Table.php b/src/DB/Table.php index 8c0f608240..4fef989445 100644 --- a/src/DB/Table.php +++ b/src/DB/Table.php @@ -134,7 +134,7 @@ protected function get_collation(): string { * * @return bool True if the column exists on the table or False if not. * - * @since x.x.x + * @since 2.5.13 */ public function has_column( string $column_name ): bool { // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared diff --git a/src/DB/TableInterface.php b/src/DB/TableInterface.php index 2c5a814efe..9b28aeab56 100644 --- a/src/DB/TableInterface.php +++ b/src/DB/TableInterface.php @@ -73,7 +73,7 @@ public function has_index( string $index_name ): bool; * * @return bool True if the column exists on the table or False if not. * - * @since x.x.x + * @since 2.5.13 */ public function has_column( string $column_name ): bool; } From 1781950d817f9ea015cf3f609ad630e2592e3911 Mon Sep 17 00:00:00 2001 From: Martyn Jones Date: Wed, 6 Dec 2023 12:54:07 +0000 Subject: [PATCH 025/135] Changelog update --- changelog.txt | 4 ++++ readme.txt | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/changelog.txt b/changelog.txt index c266100349..7e6a3fe328 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,9 @@ *** WooCommerce Google Listings and Ads Changelog *** += 2.5.13 - 2023-12-06 = +* Fix - Change Budget Recommendations values. +* Tweak - Use a single daily budget instead of a range. + = 2.5.12 - 2023-11-22 = * Dev - Fix E2E gtag events tests. * Dev - Update WordPress CS to 3.0. diff --git a/readme.txt b/readme.txt index c41187bfb9..71732d5ab5 100644 --- a/readme.txt +++ b/readme.txt @@ -111,6 +111,10 @@ Yes, you can run both at the same time, and we recommend it! In the US, advertis == Changelog == += 2.5.13 - 2023-12-06 = +* Fix - Change Budget Recommendations values. +* Tweak - Use a single daily budget instead of a range. + = 2.5.12 - 2023-11-22 = * Dev - Fix E2E gtag events tests. * Dev - Update WordPress CS to 3.0. From dd7f8def75fb469c12a6b4b29fb8d9616777fe70 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 6 Dec 2023 12:54:21 +0000 Subject: [PATCH 026/135] Update hooks documentation from branch. --- src/Hooks/README.md | 438 ++++++++++++++++++++++---------------------- 1 file changed, 219 insertions(+), 219 deletions(-) diff --git a/src/Hooks/README.md b/src/Hooks/README.md index 240c191edb..9e42b4f2a3 100644 --- a/src/Hooks/README.md +++ b/src/Hooks/README.md @@ -8,7 +8,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [BulkEditInitializer.php#L36](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Admin/BulkEdit/BulkEditInitializer.php#L36) +- [BulkEditInitializer.php#L36](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Admin/BulkEdit/BulkEditInitializer.php#L36) ## woocommerce_admin_disabled @@ -16,7 +16,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [WCAdminValidator.php#L38](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Internal/Requirements/WCAdminValidator.php#L38) +- [WCAdminValidator.php#L38](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Internal/Requirements/WCAdminValidator.php#L38) ## woocommerce_gla_ads_billing_setup_status @@ -24,8 +24,8 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [Ads.php#L112](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Ads.php#L112) -- [Ads.php#L121](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Ads.php#L121) +- [Ads.php#L112](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Ads.php#L112) +- [Ads.php#L121](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Ads.php#L121) ## woocommerce_gla_ads_client_exception @@ -33,24 +33,24 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [AdsConversionAction.php#L97](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/AdsConversionAction.php#L97) -- [AdsConversionAction.php#L143](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/AdsConversionAction.php#L143) -- [Ads.php#L73](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Ads.php#L73) -- [Ads.php#L117](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Ads.php#L117) -- [Ads.php#L172](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Ads.php#L172) -- [Ads.php#L214](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Ads.php#L214) -- [Ads.php#L298](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Ads.php#L298) -- [AdsAssetGroupAsset.php#L135](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/AdsAssetGroupAsset.php#L135) -- [AdsAssetGroupAsset.php#L201](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/AdsAssetGroupAsset.php#L201) -- [AdsAssetGroup.php#L113](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/AdsAssetGroup.php#L113) -- [AdsAssetGroup.php#L304](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/AdsAssetGroup.php#L304) -- [AdsAssetGroup.php#L368](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/AdsAssetGroup.php#L368) -- [AdsCampaign.php#L140](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/AdsCampaign.php#L140) -- [AdsCampaign.php#L183](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/AdsCampaign.php#L183) -- [AdsCampaign.php#L246](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/AdsCampaign.php#L246) -- [AdsCampaign.php#L301](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/AdsCampaign.php#L301) -- [AdsCampaign.php#L335](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/AdsCampaign.php#L335) -- [AdsReport.php#L105](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/AdsReport.php#L105) +- [AdsConversionAction.php#L97](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/AdsConversionAction.php#L97) +- [AdsConversionAction.php#L143](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/AdsConversionAction.php#L143) +- [Ads.php#L73](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Ads.php#L73) +- [Ads.php#L117](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Ads.php#L117) +- [Ads.php#L172](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Ads.php#L172) +- [Ads.php#L214](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Ads.php#L214) +- [Ads.php#L298](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Ads.php#L298) +- [AdsAssetGroupAsset.php#L135](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/AdsAssetGroupAsset.php#L135) +- [AdsAssetGroupAsset.php#L201](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/AdsAssetGroupAsset.php#L201) +- [AdsAssetGroup.php#L113](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/AdsAssetGroup.php#L113) +- [AdsAssetGroup.php#L304](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/AdsAssetGroup.php#L304) +- [AdsAssetGroup.php#L368](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/AdsAssetGroup.php#L368) +- [AdsCampaign.php#L140](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/AdsCampaign.php#L140) +- [AdsCampaign.php#L183](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/AdsCampaign.php#L183) +- [AdsCampaign.php#L246](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/AdsCampaign.php#L246) +- [AdsCampaign.php#L301](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/AdsCampaign.php#L301) +- [AdsCampaign.php#L335](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/AdsCampaign.php#L335) +- [AdsReport.php#L105](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/AdsReport.php#L105) ## woocommerce_gla_ads_setup_completed @@ -58,7 +58,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [SetupCompleteController.php#L46](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Site/Controllers/Ads/SetupCompleteController.php#L46) +- [SetupCompleteController.php#L46](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Site/Controllers/Ads/SetupCompleteController.php#L46) ## woocommerce_gla_attribute_applicable_product_types_ @@ -66,8 +66,8 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [AttributeManager.php#L295](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/Attributes/AttributeManager.php#L295) -- [AttributesForm.php#L69](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Admin/Product/Attributes/AttributesForm.php#L69) +- [AttributeManager.php#L295](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/Attributes/AttributeManager.php#L295) +- [AttributesForm.php#L69](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Admin/Product/Attributes/AttributesForm.php#L69) ## woocommerce_gla_attribute_hidden_product_types_ @@ -75,7 +75,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [AttributesForm.php#L74](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Admin/Product/Attributes/AttributesForm.php#L74) +- [AttributesForm.php#L74](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Admin/Product/Attributes/AttributesForm.php#L74) ## woocommerce_gla_attribute_mapping_sources @@ -83,7 +83,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [IsFieldTrait.php#L31](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/AttributeMapping/Traits/IsFieldTrait.php#L31) +- [IsFieldTrait.php#L31](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/AttributeMapping/Traits/IsFieldTrait.php#L31) ## woocommerce_gla_attribute_mapping_sources_custom_attributes @@ -91,7 +91,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [IsFieldTrait.php#L125](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/AttributeMapping/Traits/IsFieldTrait.php#L125) +- [IsFieldTrait.php#L125](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/AttributeMapping/Traits/IsFieldTrait.php#L125) ## woocommerce_gla_attribute_mapping_sources_global_attributes @@ -99,7 +99,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [IsFieldTrait.php#L64](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/AttributeMapping/Traits/IsFieldTrait.php#L64) +- [IsFieldTrait.php#L64](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/AttributeMapping/Traits/IsFieldTrait.php#L64) ## woocommerce_gla_attribute_mapping_sources_product_fields @@ -107,7 +107,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [IsFieldTrait.php#L115](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/AttributeMapping/Traits/IsFieldTrait.php#L115) +- [IsFieldTrait.php#L115](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/AttributeMapping/Traits/IsFieldTrait.php#L115) ## woocommerce_gla_attribute_mapping_sources_taxonomies @@ -115,7 +115,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [IsFieldTrait.php#L65](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/AttributeMapping/Traits/IsFieldTrait.php#L65) +- [IsFieldTrait.php#L65](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/AttributeMapping/Traits/IsFieldTrait.php#L65) ## woocommerce_gla_attributes_tab_applicable_product_types @@ -123,7 +123,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [AttributesTab.php#L174](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Admin/Product/Attributes/AttributesTab.php#L174) +- [AttributesTab.php#L174](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Admin/Product/Attributes/AttributesTab.php#L174) ## woocommerce_gla_batch_deleted_products @@ -131,7 +131,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ProductSyncer.php#L229](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L229) +- [ProductSyncer.php#L229](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L229) ## woocommerce_gla_batch_retry_delete_products @@ -139,7 +139,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ProductSyncer.php#L343](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L343) +- [ProductSyncer.php#L343](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L343) ## woocommerce_gla_batch_retry_update_products @@ -147,7 +147,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ProductSyncer.php#L287](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L287) +- [ProductSyncer.php#L287](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L287) ## woocommerce_gla_batch_updated_products @@ -155,7 +155,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ProductSyncer.php#L143](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L143) +- [ProductSyncer.php#L143](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L143) ## woocommerce_gla_batched_job_size @@ -163,8 +163,8 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [AbstractBatchedActionSchedulerJob.php#L104](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Jobs/AbstractBatchedActionSchedulerJob.php#L104) -- [UpdateSyncableProductsCount.php#L74](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Jobs/UpdateSyncableProductsCount.php#L74) +- [AbstractBatchedActionSchedulerJob.php#L104](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Jobs/AbstractBatchedActionSchedulerJob.php#L104) +- [UpdateSyncableProductsCount.php#L74](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Jobs/UpdateSyncableProductsCount.php#L74) ## woocommerce_gla_bulk_update_coupon @@ -172,7 +172,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [CouponBulkEdit.php#L133](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Admin/BulkEdit/CouponBulkEdit.php#L133) +- [CouponBulkEdit.php#L133](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Admin/BulkEdit/CouponBulkEdit.php#L133) ## woocommerce_gla_conversion_action_name @@ -180,7 +180,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [AdsConversionAction.php#L66](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/AdsConversionAction.php#L66) +- [AdsConversionAction.php#L66](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/AdsConversionAction.php#L66) ## woocommerce_gla_coupon_destinations @@ -188,7 +188,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [WCCouponAdapter.php#L391](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/WCCouponAdapter.php#L391) +- [WCCouponAdapter.php#L391](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/WCCouponAdapter.php#L391) ## woocommerce_gla_coupons_delete_retry_on_failure @@ -196,7 +196,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [CouponSyncer.php#L438](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L438) +- [CouponSyncer.php#L438](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L438) ## woocommerce_gla_coupons_update_retry_on_failure @@ -204,7 +204,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [CouponSyncer.php#L400](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L400) +- [CouponSyncer.php#L400](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L400) ## woocommerce_gla_custom_merchant_issues @@ -212,7 +212,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [MerchantStatuses.php#L435](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/MerchantCenter/MerchantStatuses.php#L435) +- [MerchantStatuses.php#L435](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/MerchantCenter/MerchantStatuses.php#L435) ## woocommerce_gla_debug_message @@ -220,38 +220,38 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [MerchantStatuses.php#L334](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/MerchantCenter/MerchantStatuses.php#L334) -- [MerchantStatuses.php#L357](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/MerchantCenter/MerchantStatuses.php#L357) -- [MerchantCenterService.php#L305](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/MerchantCenter/MerchantCenterService.php#L305) -- [SyncerHooks.php#L197](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/SyncerHooks.php#L197) -- [WCProductAdapter.php#L202](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/WCProductAdapter.php#L202) -- [ProductSyncer.php#L149](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L149) -- [ProductSyncer.php#L159](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L159) -- [ProductSyncer.php#L235](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L235) -- [ProductSyncer.php#L245](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L245) -- [ProductHelper.php#L458](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductHelper.php#L458) -- [ProductHelper.php#L490](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductHelper.php#L490) -- [ProductRepository.php#L304](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductRepository.php#L304) -- [BatchProductHelper.php#L208](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/BatchProductHelper.php#L208) -- [BatchProductHelper.php#L231](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/BatchProductHelper.php#L231) -- [SyncerHooks.php#L178](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/SyncerHooks.php#L178) -- [CouponHelper.php#L257](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponHelper.php#L257) -- [CouponHelper.php#L294](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponHelper.php#L294) -- [CouponSyncer.php#L103](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L103) -- [CouponSyncer.php#L116](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L116) -- [CouponSyncer.php#L141](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L141) -- [CouponSyncer.php#L155](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L155) -- [CouponSyncer.php#L172](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L172) -- [CouponSyncer.php#L195](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L195) -- [CouponSyncer.php#L260](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L260) -- [CouponSyncer.php#L309](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L309) -- [CouponSyncer.php#L328](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L328) -- [ProductMetaQueryHelper.php#L92](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/DB/ProductMetaQueryHelper.php#L92) -- [ProductMetaQueryHelper.php#L123](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/DB/ProductMetaQueryHelper.php#L123) -- [ActionSchedulerJobMonitor.php#L117](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Jobs/ActionSchedulerJobMonitor.php#L117) -- [ActionSchedulerJobMonitor.php#L126](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Jobs/ActionSchedulerJobMonitor.php#L126) -- [CleanupSyncedProducts.php#L74](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Jobs/CleanupSyncedProducts.php#L74) -- [IssuesController.php#L96](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Site/Controllers/MerchantCenter/IssuesController.php#L96) +- [MerchantStatuses.php#L334](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/MerchantCenter/MerchantStatuses.php#L334) +- [MerchantStatuses.php#L357](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/MerchantCenter/MerchantStatuses.php#L357) +- [MerchantCenterService.php#L305](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/MerchantCenter/MerchantCenterService.php#L305) +- [SyncerHooks.php#L197](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/SyncerHooks.php#L197) +- [WCProductAdapter.php#L202](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/WCProductAdapter.php#L202) +- [ProductSyncer.php#L149](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L149) +- [ProductSyncer.php#L159](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L159) +- [ProductSyncer.php#L235](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L235) +- [ProductSyncer.php#L245](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L245) +- [ProductHelper.php#L458](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductHelper.php#L458) +- [ProductHelper.php#L490](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductHelper.php#L490) +- [ProductRepository.php#L304](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductRepository.php#L304) +- [BatchProductHelper.php#L208](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/BatchProductHelper.php#L208) +- [BatchProductHelper.php#L231](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/BatchProductHelper.php#L231) +- [SyncerHooks.php#L178](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/SyncerHooks.php#L178) +- [CouponHelper.php#L257](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponHelper.php#L257) +- [CouponHelper.php#L294](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponHelper.php#L294) +- [CouponSyncer.php#L103](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L103) +- [CouponSyncer.php#L116](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L116) +- [CouponSyncer.php#L141](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L141) +- [CouponSyncer.php#L155](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L155) +- [CouponSyncer.php#L172](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L172) +- [CouponSyncer.php#L195](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L195) +- [CouponSyncer.php#L260](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L260) +- [CouponSyncer.php#L309](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L309) +- [CouponSyncer.php#L328](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L328) +- [ProductMetaQueryHelper.php#L92](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/DB/ProductMetaQueryHelper.php#L92) +- [ProductMetaQueryHelper.php#L123](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/DB/ProductMetaQueryHelper.php#L123) +- [ActionSchedulerJobMonitor.php#L117](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Jobs/ActionSchedulerJobMonitor.php#L117) +- [ActionSchedulerJobMonitor.php#L126](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Jobs/ActionSchedulerJobMonitor.php#L126) +- [CleanupSyncedProducts.php#L74](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Jobs/CleanupSyncedProducts.php#L74) +- [IssuesController.php#L96](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Site/Controllers/MerchantCenter/IssuesController.php#L96) ## woocommerce_gla_deleted_promotions @@ -259,7 +259,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [CouponSyncer.php#L322](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L322) +- [CouponSyncer.php#L322](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L322) ## woocommerce_gla_dimension_unit @@ -267,7 +267,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [WCProductAdapter.php#L426](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/WCProductAdapter.php#L426) +- [WCProductAdapter.php#L426](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/WCProductAdapter.php#L426) ## woocommerce_gla_disable_gtag_tracking @@ -275,7 +275,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [GlobalSiteTag.php#L464](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Google/GlobalSiteTag.php#L464) +- [GlobalSiteTag.php#L464](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Google/GlobalSiteTag.php#L464) ## woocommerce_gla_enable_connection_test @@ -283,7 +283,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ConnectionTest.php#L87](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/ConnectionTest.php#L87) +- [ConnectionTest.php#L87](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/ConnectionTest.php#L87) ## woocommerce_gla_enable_debug_logging @@ -291,7 +291,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [DebugLogger.php#L33](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Logging/DebugLogger.php#L33) +- [DebugLogger.php#L33](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Logging/DebugLogger.php#L33) ## woocommerce_gla_enable_mcm @@ -299,7 +299,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [GLAChannel.php#L75](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/MultichannelMarketing/GLAChannel.php#L75) +- [GLAChannel.php#L75](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/MultichannelMarketing/GLAChannel.php#L75) ## woocommerce_gla_enable_reports @@ -307,7 +307,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [Admin.php#L265](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Admin/Admin.php#L265) +- [Admin.php#L265](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Admin/Admin.php#L265) ## woocommerce_gla_error @@ -315,23 +315,23 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [PHPView.php#L136](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/View/PHPView.php#L136) -- [PHPView.php#L164](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/View/PHPView.php#L164) -- [PHPView.php#L208](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/View/PHPView.php#L208) -- [ProductSyncer.php#L290](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L290) -- [ProductSyncer.php#L313](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L313) -- [ProductSyncer.php#L346](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L346) -- [ProductSyncer.php#L361](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L361) -- [ProductHelper.php#L350](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductHelper.php#L350) -- [ProductHelper.php#L566](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductHelper.php#L566) -- [AttributeManager.php#L269](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/Attributes/AttributeManager.php#L269) -- [ProductMetaHandler.php#L173](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductMetaHandler.php#L173) -- [BatchProductHelper.php#L248](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/BatchProductHelper.php#L248) -- [CouponMetaHandler.php#L220](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponMetaHandler.php#L220) -- [CouponSyncer.php#L410](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L410) -- [CouponSyncer.php#L448](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L448) -- [CouponSyncer.php#L466](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L466) -- [ProductMetaQueryHelper.php#L139](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/DB/ProductMetaQueryHelper.php#L139) +- [PHPView.php#L136](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/View/PHPView.php#L136) +- [PHPView.php#L164](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/View/PHPView.php#L164) +- [PHPView.php#L208](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/View/PHPView.php#L208) +- [ProductSyncer.php#L290](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L290) +- [ProductSyncer.php#L313](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L313) +- [ProductSyncer.php#L346](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L346) +- [ProductSyncer.php#L361](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L361) +- [ProductHelper.php#L350](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductHelper.php#L350) +- [ProductHelper.php#L566](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductHelper.php#L566) +- [AttributeManager.php#L269](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/Attributes/AttributeManager.php#L269) +- [ProductMetaHandler.php#L173](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductMetaHandler.php#L173) +- [BatchProductHelper.php#L248](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/BatchProductHelper.php#L248) +- [CouponMetaHandler.php#L220](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponMetaHandler.php#L220) +- [CouponSyncer.php#L410](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L410) +- [CouponSyncer.php#L448](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L448) +- [CouponSyncer.php#L466](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L466) +- [ProductMetaQueryHelper.php#L139](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/DB/ProductMetaQueryHelper.php#L139) ## woocommerce_gla_exception @@ -339,27 +339,27 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [PHPView.php#L87](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/View/PHPView.php#L87) -- [ProductSyncer.php#L134](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L134) -- [ProductSyncer.php#L220](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L220) -- [NoteInitializer.php#L74](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Notes/NoteInitializer.php#L74) -- [NoteInitializer.php#L116](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Notes/NoteInitializer.php#L116) -- [CouponSyncer.php#L203](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L203) -- [CouponSyncer.php#L293](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L293) -- [WooCommercePreOrders.php#L111](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Integration/WooCommercePreOrders.php#L111) -- [WooCommercePreOrders.php#L131](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Integration/WooCommercePreOrders.php#L131) -- [GoogleServiceProvider.php#L232](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Internal/DependencyManagement/GoogleServiceProvider.php#L232) -- [DateTime.php#L44](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Admin/Input/DateTime.php#L44) -- [DateTime.php#L80](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Admin/Input/DateTime.php#L80) -- [ChannelVisibilityMetaBox.php#L176](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Admin/MetaBox/ChannelVisibilityMetaBox.php#L176) -- [CouponChannelVisibilityMetaBox.php#L197](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Admin/MetaBox/CouponChannelVisibilityMetaBox.php#L197) -- [PluginUpdate.php#L75](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Jobs/Update/PluginUpdate.php#L75) -- [Connection.php#L95](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Connection.php#L95) -- [ProductVisibilityController.php#L193](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Site/Controllers/MerchantCenter/ProductVisibilityController.php#L193) -- [SettingsSyncController.php#L79](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Site/Controllers/MerchantCenter/SettingsSyncController.php#L79) -- [ContactInformationController.php#L242](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Site/Controllers/MerchantCenter/ContactInformationController.php#L242) -- [ScriptWithBuiltDependenciesAsset.php#L66](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Assets/ScriptWithBuiltDependenciesAsset.php#L66) -- [ClearProductStatsCache.php#L61](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Event/ClearProductStatsCache.php#L61) +- [PHPView.php#L87](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/View/PHPView.php#L87) +- [ProductSyncer.php#L134](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L134) +- [ProductSyncer.php#L220](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L220) +- [NoteInitializer.php#L74](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Notes/NoteInitializer.php#L74) +- [NoteInitializer.php#L116](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Notes/NoteInitializer.php#L116) +- [CouponSyncer.php#L203](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L203) +- [CouponSyncer.php#L293](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L293) +- [WooCommercePreOrders.php#L111](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Integration/WooCommercePreOrders.php#L111) +- [WooCommercePreOrders.php#L131](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Integration/WooCommercePreOrders.php#L131) +- [GoogleServiceProvider.php#L232](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Internal/DependencyManagement/GoogleServiceProvider.php#L232) +- [DateTime.php#L44](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Admin/Input/DateTime.php#L44) +- [DateTime.php#L80](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Admin/Input/DateTime.php#L80) +- [ChannelVisibilityMetaBox.php#L176](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Admin/MetaBox/ChannelVisibilityMetaBox.php#L176) +- [CouponChannelVisibilityMetaBox.php#L197](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Admin/MetaBox/CouponChannelVisibilityMetaBox.php#L197) +- [PluginUpdate.php#L75](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Jobs/Update/PluginUpdate.php#L75) +- [Connection.php#L95](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Connection.php#L95) +- [ProductVisibilityController.php#L193](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Site/Controllers/MerchantCenter/ProductVisibilityController.php#L193) +- [SettingsSyncController.php#L79](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Site/Controllers/MerchantCenter/SettingsSyncController.php#L79) +- [ContactInformationController.php#L242](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Site/Controllers/MerchantCenter/ContactInformationController.php#L242) +- [ScriptWithBuiltDependenciesAsset.php#L66](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Assets/ScriptWithBuiltDependenciesAsset.php#L66) +- [ClearProductStatsCache.php#L61](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Event/ClearProductStatsCache.php#L61) ## woocommerce_gla_force_run_install @@ -367,7 +367,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [Installer.php#L82](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Installer.php#L82) +- [Installer.php#L82](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Installer.php#L82) ## woocommerce_gla_get_google_product_offer_id @@ -375,7 +375,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [WCProductAdapter.php#L279](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/WCProductAdapter.php#L279) +- [WCProductAdapter.php#L279](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/WCProductAdapter.php#L279) ## woocommerce_gla_get_sync_ready_products_filter @@ -383,7 +383,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ProductFilter.php#L61](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductFilter.php#L61) +- [ProductFilter.php#L61](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductFilter.php#L61) ## woocommerce_gla_get_sync_ready_products_pre_filter @@ -391,7 +391,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ProductFilter.php#L47](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductFilter.php#L47) +- [ProductFilter.php#L47](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductFilter.php#L47) ## woocommerce_gla_get_wc_product_id @@ -399,7 +399,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ProductHelper.php#L277](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductHelper.php#L277) +- [ProductHelper.php#L277](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductHelper.php#L277) ## woocommerce_gla_guzzle_client_exception @@ -407,20 +407,20 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [GoogleServiceProvider.php#L256](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Internal/DependencyManagement/GoogleServiceProvider.php#L256) -- [Connection.php#L70](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Connection.php#L70) -- [Connection.php#L91](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Connection.php#L91) -- [Connection.php#L126](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Connection.php#L126) -- [Middleware.php#L80](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L80) -- [Middleware.php#L178](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L178) -- [Middleware.php#L228](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L228) -- [Middleware.php#L273](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L273) -- [Middleware.php#L344](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L344) -- [Middleware.php#L394](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L394) -- [Middleware.php#L418](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L418) -- [Middleware.php#L452](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L452) -- [Middleware.php#L552](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L552) -- [Middleware.php#L611](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L611) +- [GoogleServiceProvider.php#L256](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Internal/DependencyManagement/GoogleServiceProvider.php#L256) +- [Connection.php#L70](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Connection.php#L70) +- [Connection.php#L91](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Connection.php#L91) +- [Connection.php#L126](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Connection.php#L126) +- [Middleware.php#L80](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L80) +- [Middleware.php#L178](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L178) +- [Middleware.php#L228](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L228) +- [Middleware.php#L273](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L273) +- [Middleware.php#L344](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L344) +- [Middleware.php#L394](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L394) +- [Middleware.php#L418](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L418) +- [Middleware.php#L452](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L452) +- [Middleware.php#L552](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L552) +- [Middleware.php#L611](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L611) ## woocommerce_gla_guzzle_invalid_response @@ -428,15 +428,15 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [Connection.php#L66](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Connection.php#L66) -- [Connection.php#L121](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Connection.php#L121) -- [Middleware.php#L159](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L159) -- [Middleware.php#L223](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L223) -- [Middleware.php#L267](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L267) -- [Middleware.php#L339](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L339) -- [Middleware.php#L389](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L389) -- [Middleware.php#L548](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L548) -- [Middleware.php#L599](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L599) +- [Connection.php#L66](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Connection.php#L66) +- [Connection.php#L121](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Connection.php#L121) +- [Middleware.php#L159](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L159) +- [Middleware.php#L223](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L223) +- [Middleware.php#L267](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L267) +- [Middleware.php#L339](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L339) +- [Middleware.php#L389](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L389) +- [Middleware.php#L548](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L548) +- [Middleware.php#L599](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L599) ## woocommerce_gla_handle_shipping_method_to_rates @@ -444,7 +444,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ZoneMethodsParser.php#L106](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Shipping/ZoneMethodsParser.php#L106) +- [ZoneMethodsParser.php#L106](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Shipping/ZoneMethodsParser.php#L106) ## woocommerce_gla_hidden_coupon_types @@ -452,7 +452,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [CouponSyncer.php#L379](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L379) +- [CouponSyncer.php#L379](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L379) ## woocommerce_gla_job_failure_rate_threshold @@ -460,7 +460,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ActionSchedulerJobMonitor.php#L186](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Jobs/ActionSchedulerJobMonitor.php#L186) +- [ActionSchedulerJobMonitor.php#L186](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Jobs/ActionSchedulerJobMonitor.php#L186) ## woocommerce_gla_job_failure_timeframe @@ -468,7 +468,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ActionSchedulerJobMonitor.php#L195](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Jobs/ActionSchedulerJobMonitor.php#L195) +- [ActionSchedulerJobMonitor.php#L195](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Jobs/ActionSchedulerJobMonitor.php#L195) ## woocommerce_gla_mapping_rules_change @@ -476,9 +476,9 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [AttributeMappingRulesController.php#L143](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Site/Controllers/AttributeMapping/AttributeMappingRulesController.php#L143) -- [AttributeMappingRulesController.php#L166](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Site/Controllers/AttributeMapping/AttributeMappingRulesController.php#L166) -- [AttributeMappingRulesController.php#L188](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Site/Controllers/AttributeMapping/AttributeMappingRulesController.php#L188) +- [AttributeMappingRulesController.php#L143](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Site/Controllers/AttributeMapping/AttributeMappingRulesController.php#L143) +- [AttributeMappingRulesController.php#L166](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Site/Controllers/AttributeMapping/AttributeMappingRulesController.php#L166) +- [AttributeMappingRulesController.php#L188](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Site/Controllers/AttributeMapping/AttributeMappingRulesController.php#L188) ## woocommerce_gla_mc_account_review_lifetime @@ -486,7 +486,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [RequestReviewStatuses.php#L146](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Google/RequestReviewStatuses.php#L146) +- [RequestReviewStatuses.php#L146](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Google/RequestReviewStatuses.php#L146) ## woocommerce_gla_mc_client_exception @@ -494,14 +494,14 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [MerchantReport.php#L95](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/MerchantReport.php#L95) -- [Merchant.php#L92](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Merchant.php#L92) -- [Merchant.php#L140](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Merchant.php#L140) -- [Merchant.php#L172](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Merchant.php#L172) -- [Merchant.php#L191](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Merchant.php#L191) -- [Merchant.php#L247](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Merchant.php#L247) -- [Merchant.php#L292](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Merchant.php#L292) -- [Merchant.php#L354](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Merchant.php#L354) +- [MerchantReport.php#L95](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/MerchantReport.php#L95) +- [Merchant.php#L92](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Merchant.php#L92) +- [Merchant.php#L140](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Merchant.php#L140) +- [Merchant.php#L172](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Merchant.php#L172) +- [Merchant.php#L191](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Merchant.php#L191) +- [Merchant.php#L247](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Merchant.php#L247) +- [Merchant.php#L292](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Merchant.php#L292) +- [Merchant.php#L354](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Merchant.php#L354) ## woocommerce_gla_mc_settings_sync @@ -509,7 +509,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [SettingsSyncController.php#L69](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Site/Controllers/MerchantCenter/SettingsSyncController.php#L69) +- [SettingsSyncController.php#L69](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Site/Controllers/MerchantCenter/SettingsSyncController.php#L69) ## woocommerce_gla_mc_status_lifetime @@ -517,7 +517,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [MerchantStatuses.php#L778](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/MerchantCenter/MerchantStatuses.php#L778) +- [MerchantStatuses.php#L778](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/MerchantCenter/MerchantStatuses.php#L778) ## woocommerce_gla_merchant_issue_override @@ -525,7 +525,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [IssuesController.php#L86](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Site/Controllers/MerchantCenter/IssuesController.php#L86) +- [IssuesController.php#L86](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Site/Controllers/MerchantCenter/IssuesController.php#L86) ## woocommerce_gla_merchant_status_google_ids_chunk @@ -533,7 +533,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [MerchantStatuses.php#L191](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/MerchantCenter/MerchantStatuses.php#L191) +- [MerchantStatuses.php#L191](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/MerchantCenter/MerchantStatuses.php#L191) ## woocommerce_gla_merchant_status_presync_issues_chunk @@ -541,7 +541,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [MerchantStatuses.php#L531](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/MerchantCenter/MerchantStatuses.php#L531) +- [MerchantStatuses.php#L531](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/MerchantCenter/MerchantStatuses.php#L531) ## woocommerce_gla_options_deleted_ @@ -549,7 +549,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [Options.php#L103](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Options/Options.php#L103) +- [Options.php#L103](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Options/Options.php#L103) ## woocommerce_gla_options_updated_ @@ -557,8 +557,8 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [Options.php#L65](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Options/Options.php#L65) -- [Options.php#L85](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Options/Options.php#L85) +- [Options.php#L65](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Options/Options.php#L65) +- [Options.php#L85](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Options/Options.php#L85) ## woocommerce_gla_prepared_response_->GET_ROUTE_NAME @@ -566,7 +566,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [BaseController.php#L160](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Site/Controllers/BaseController.php#L160) +- [BaseController.php#L160](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Site/Controllers/BaseController.php#L160) ## woocommerce_gla_product_attribute_types @@ -574,7 +574,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [AttributeManager.php#L243](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/Attributes/AttributeManager.php#L243) +- [AttributeManager.php#L243](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/Attributes/AttributeManager.php#L243) ## woocommerce_gla_product_attribute_value_ @@ -582,8 +582,8 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [WCProductAdapter.php#L905](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/WCProductAdapter.php#L905) -- [WCProductAdapter.php#L956](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/WCProductAdapter.php#L956) +- [WCProductAdapter.php#L905](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/WCProductAdapter.php#L905) +- [WCProductAdapter.php#L956](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/WCProductAdapter.php#L956) ## woocommerce_gla_product_attribute_value_description @@ -591,7 +591,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [WCProductAdapter.php#L347](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/WCProductAdapter.php#L347) +- [WCProductAdapter.php#L347](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/WCProductAdapter.php#L347) ## woocommerce_gla_product_attribute_value_options_::get_id @@ -599,7 +599,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [AttributesForm.php#L108](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Admin/Product/Attributes/AttributesForm.php#L108) +- [AttributesForm.php#L108](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Admin/Product/Attributes/AttributesForm.php#L108) ## woocommerce_gla_product_attribute_value_price @@ -607,7 +607,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [WCProductAdapter.php#L629](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/WCProductAdapter.php#L629) +- [WCProductAdapter.php#L629](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/WCProductAdapter.php#L629) ## woocommerce_gla_product_attribute_value_sale_price @@ -615,7 +615,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [WCProductAdapter.php#L681](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/WCProductAdapter.php#L681) +- [WCProductAdapter.php#L681](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/WCProductAdapter.php#L681) ## woocommerce_gla_product_attribute_values @@ -623,7 +623,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [WCProductAdapter.php#L166](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/WCProductAdapter.php#L166) +- [WCProductAdapter.php#L166](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/WCProductAdapter.php#L166) ## woocommerce_gla_product_description_apply_shortcodes @@ -631,7 +631,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [WCProductAdapter.php#L316](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/WCProductAdapter.php#L316) +- [WCProductAdapter.php#L316](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/WCProductAdapter.php#L316) ## woocommerce_gla_product_property_value_is_virtual @@ -639,7 +639,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [WCProductAdapter.php#L771](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/WCProductAdapter.php#L771) +- [WCProductAdapter.php#L771](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/WCProductAdapter.php#L771) ## woocommerce_gla_product_query_args @@ -647,7 +647,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ProductRepository.php#L360](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductRepository.php#L360) +- [ProductRepository.php#L360](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductRepository.php#L360) ## woocommerce_gla_products_delete_retry_on_failure @@ -655,7 +655,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ProductSyncer.php#L342](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L342) +- [ProductSyncer.php#L342](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L342) ## woocommerce_gla_products_update_retry_on_failure @@ -663,7 +663,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ProductSyncer.php#L286](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L286) +- [ProductSyncer.php#L286](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L286) ## woocommerce_gla_ready_for_syncing @@ -671,7 +671,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [MerchantCenterService.php#L118](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/MerchantCenter/MerchantCenterService.php#L118) +- [MerchantCenterService.php#L118](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/MerchantCenter/MerchantCenterService.php#L118) ## woocommerce_gla_request_review_failure @@ -679,9 +679,9 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [Middleware.php#L592](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L592) -- [RequestReviewController.php#L110](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Site/Controllers/MerchantCenter/RequestReviewController.php#L110) -- [RequestReviewController.php#L122](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Site/Controllers/MerchantCenter/RequestReviewController.php#L122) +- [Middleware.php#L592](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L592) +- [RequestReviewController.php#L110](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Site/Controllers/MerchantCenter/RequestReviewController.php#L110) +- [RequestReviewController.php#L122](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Site/Controllers/MerchantCenter/RequestReviewController.php#L122) ## woocommerce_gla_request_review_response @@ -689,7 +689,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [Middleware.php#L545](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L545) +- [Middleware.php#L545](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L545) ## woocommerce_gla_retry_delete_coupons @@ -697,7 +697,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [CouponSyncer.php#L443](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L443) +- [CouponSyncer.php#L443](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L443) ## woocommerce_gla_retry_update_coupons @@ -705,7 +705,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [CouponSyncer.php#L405](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L405) +- [CouponSyncer.php#L405](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L405) ## woocommerce_gla_site_claim_failure @@ -713,10 +713,10 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [AccountService.php#L365](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/MerchantCenter/AccountService.php#L365) -- [Merchant.php#L93](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Merchant.php#L93) -- [Middleware.php#L268](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L268) -- [Middleware.php#L274](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L274) +- [AccountService.php#L365](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/MerchantCenter/AccountService.php#L365) +- [Merchant.php#L93](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Merchant.php#L93) +- [Middleware.php#L268](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L268) +- [Middleware.php#L274](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L274) ## woocommerce_gla_site_claim_overwrite_required @@ -724,7 +724,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [AccountService.php#L360](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/MerchantCenter/AccountService.php#L360) +- [AccountService.php#L360](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/MerchantCenter/AccountService.php#L360) ## woocommerce_gla_site_claim_success @@ -732,8 +732,8 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [Merchant.php#L90](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Merchant.php#L90) -- [Middleware.php#L263](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/Middleware.php#L263) +- [Merchant.php#L90](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Merchant.php#L90) +- [Middleware.php#L263](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/Middleware.php#L263) ## woocommerce_gla_site_url @@ -741,7 +741,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [PluginHelper.php#L189](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/PluginHelper.php#L189) +- [PluginHelper.php#L189](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/PluginHelper.php#L189) ## woocommerce_gla_site_verify_failure @@ -749,9 +749,9 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [SiteVerification.php#L58](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/SiteVerification.php#L58) -- [SiteVerification.php#L66](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/SiteVerification.php#L66) -- [SiteVerification.php#L87](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/SiteVerification.php#L87) +- [SiteVerification.php#L58](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/SiteVerification.php#L58) +- [SiteVerification.php#L66](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/SiteVerification.php#L66) +- [SiteVerification.php#L87](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/SiteVerification.php#L87) ## woocommerce_gla_site_verify_success @@ -759,7 +759,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [SiteVerification.php#L85](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/SiteVerification.php#L85) +- [SiteVerification.php#L85](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/SiteVerification.php#L85) ## woocommerce_gla_supported_coupon_types @@ -767,7 +767,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [CouponSyncer.php#L366](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L366) +- [CouponSyncer.php#L366](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L366) ## woocommerce_gla_supported_product_types @@ -775,7 +775,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ProductSyncer.php#L264](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductSyncer.php#L264) +- [ProductSyncer.php#L264](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductSyncer.php#L264) ## woocommerce_gla_sv_client_exception @@ -783,8 +783,8 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [SiteVerification.php#L120](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/SiteVerification.php#L120) -- [SiteVerification.php#L162](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/API/Google/SiteVerification.php#L162) +- [SiteVerification.php#L120](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/SiteVerification.php#L120) +- [SiteVerification.php#L162](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/API/Google/SiteVerification.php#L162) ## woocommerce_gla_tax_excluded @@ -792,7 +792,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [WCProductAdapter.php#L590](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/WCProductAdapter.php#L590) +- [WCProductAdapter.php#L590](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/WCProductAdapter.php#L590) ## woocommerce_gla_updated_coupon @@ -800,7 +800,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [CouponSyncer.php#L169](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Coupon/CouponSyncer.php#L169) +- [CouponSyncer.php#L169](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Coupon/CouponSyncer.php#L169) ## woocommerce_gla_url_switch_required @@ -808,7 +808,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [AccountService.php#L445](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/MerchantCenter/AccountService.php#L445) +- [AccountService.php#L445](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/MerchantCenter/AccountService.php#L445) ## woocommerce_gla_url_switch_success @@ -816,7 +816,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [AccountService.php#L468](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/MerchantCenter/AccountService.php#L468) +- [AccountService.php#L468](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/MerchantCenter/AccountService.php#L468) ## woocommerce_gla_use_short_description @@ -824,7 +824,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [WCProductAdapter.php#L293](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/WCProductAdapter.php#L293) +- [WCProductAdapter.php#L293](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/WCProductAdapter.php#L293) ## woocommerce_gla_wcs_url @@ -832,8 +832,8 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [PluginHelper.php#L174](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/PluginHelper.php#L174) -- [PluginHelper.php#L178](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/PluginHelper.php#L178) +- [PluginHelper.php#L174](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/PluginHelper.php#L174) +- [PluginHelper.php#L178](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/PluginHelper.php#L178) ## woocommerce_gla_weight_unit @@ -841,7 +841,7 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [WCProductAdapter.php#L427](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/WCProductAdapter.php#L427) +- [WCProductAdapter.php#L427](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/WCProductAdapter.php#L427) ## woocommerce_hide_invisible_variations @@ -849,5 +849,5 @@ A list of hooks, e.g. `actions` and `filters`, that are defined or used in this **Used in**: -- [ProductHelper.php#L365](https://github.com/woocommerce/google-listings-and-ads/blob/3cacf043e0a630c35a047f8c1678d528bd703178/src/Product/ProductHelper.php#L365) +- [ProductHelper.php#L365](https://github.com/woocommerce/google-listings-and-ads/blob/6eac07a6c9bf335d08c911cb6ecefbee58175a06/src/Product/ProductHelper.php#L365) From 7072aeaf64e362783aae6e0b7ebaff0e654a1b00 Mon Sep 17 00:00:00 2001 From: Miguel Perez Pellicer <5908855+puntope@users.noreply.github.com> Date: Thu, 30 Nov 2023 20:12:45 -0300 Subject: [PATCH 027/135] Add (budget and audiences) tracking for Onboarding completed with Ads --- .../setup-paid-ads/setup-paid-ads.js | 15 +++++++++++++ src/Tracking/README.md | 22 ++++++++++++++----- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js b/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js index 8bc19b9dfa..8fb9a41865 100644 --- a/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js +++ b/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js @@ -7,6 +7,7 @@ import { select } from '@wordpress/data'; import { useState } from '@wordpress/element'; import { Flex } from '@wordpress/components'; import { noop, merge } from 'lodash'; +import { recordEvent } from '@woocommerce/tracks'; /** * Internal dependencies @@ -42,6 +43,14 @@ const ACTION_SKIP = 'skip-ads'; * @event gla_onboarding_complete_with_paid_ads_button_click */ +/** + * When the Onboarding is completed with Ads Setup. + * + * @event gla_onboarding_complete_ads_setup + * @property {number} budget The budget for the campaign + * @property {number} audiences The targeted audiences for the campaign + */ + /** * Clicking on the skip paid ads button to complete the onboarding flow. * The 'unknown' value of properties may means: @@ -63,6 +72,7 @@ const ACTION_SKIP = 'skip-ads'; * @fires gla_onboarding_open_paid_ads_setup_button_click * @fires gla_onboarding_complete_with_paid_ads_button_click * @fires gla_onboarding_complete_button_click + * @fires gla_onboarding_complete_ads_setup */ export default function SetupPaidAds() { const adminUrl = useAdminUrl(); @@ -100,6 +110,11 @@ export default function SetupPaidAds() { ); } + recordEvent( 'gla_onboarding_complete_ads_setup', { + budget: paidAds.amount, + audiences: paidAds.countryCodes.join( ',' ), + } ); + // Force reload WC admin page to initiate the relevant dependencies of the Dashboard page. const query = { guide: GUIDE_NAMES.SUBMISSION_SUCCESS }; window.location.href = adminUrl + getProductFeedUrl( query ); diff --git a/src/Tracking/README.md b/src/Tracking/README.md index 3a301c3238..bc7ebc3556 100644 --- a/src/Tracking/README.md +++ b/src/Tracking/README.md @@ -571,7 +571,17 @@ A modal is open - [`ReviewRequest`](../../js/src/product-feed/review-request/index.js#L31) with `context: REQUEST_REVIEW` - [`SubmissionSuccessGuide`](../../js/src/product-feed/submission-success-guide/index.js#L155) with `context: GUIDE_NAMES.SUBMISSION_SUCCESS` -### [`gla_onboarding_complete_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L45) +### [`gla_onboarding_complete_ads_setup`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L46) +When the Onboarding is completed with Ads Setup. +#### Properties +| name | type | description | +| ---- | ---- | ----------- | +`budget` | `number` | The budget for the campaign +`audiences` | `number` | The targeted audiences for the campaign +#### Emitters +- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L77) + +### [`gla_onboarding_complete_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L54) Clicking on the skip paid ads button to complete the onboarding flow. The 'unknown' value of properties may means: - the paid ads setup is not opened @@ -585,17 +595,17 @@ Clicking on the skip paid ads button to complete the onboarding flow. `billing_method_status` | `string` | aaa, The status of billing method of merchant's Google Ads addcount e.g. 'unknown', 'pending', 'approved', 'cancelled' `campaign_form_validation` | `string` | Whether the entered paid campaign form data are valid, e.g. 'unknown', 'valid', 'invalid' #### Emitters -- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L67) +- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L77) -### [`gla_onboarding_complete_with_paid_ads_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L39) +### [`gla_onboarding_complete_with_paid_ads_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L40) Clicking on the "Complete setup" button to complete the onboarding flow with paid ads. #### Emitters -- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L67) +- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L77) -### [`gla_onboarding_open_paid_ads_setup_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L33) +### [`gla_onboarding_open_paid_ads_setup_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L34) Clicking on the "Create a paid ad campaign" button to open the paid ads setup in the onboarding flow. #### Emitters -- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L67) +- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L77) ### [`gla_paid_campaign_step`](../../js/src/utils/recordEvent.js#L122) Triggered when moving to another step during creating/editing a campaign. From 7da36c0254f641ce08856bd704ce4d8af3cda9e8 Mon Sep 17 00:00:00 2001 From: Miguel Perez Pellicer <5908855+puntope@users.noreply.github.com> Date: Mon, 11 Dec 2023 18:21:01 -0300 Subject: [PATCH 028/135] Add audiences and budget inside existing gla_onboarding_complete_with_paid_ads_button_click --- .../setup-paid-ads/setup-paid-ads.js | 19 ++++--------- src/Tracking/README.md | 27 ++++++++----------- 2 files changed, 16 insertions(+), 30 deletions(-) diff --git a/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js b/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js index 8fb9a41865..a28a7b78ab 100644 --- a/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js +++ b/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js @@ -7,7 +7,6 @@ import { select } from '@wordpress/data'; import { useState } from '@wordpress/element'; import { Flex } from '@wordpress/components'; import { noop, merge } from 'lodash'; -import { recordEvent } from '@woocommerce/tracks'; /** * Internal dependencies @@ -41,14 +40,8 @@ const ACTION_SKIP = 'skip-ads'; * Clicking on the "Complete setup" button to complete the onboarding flow with paid ads. * * @event gla_onboarding_complete_with_paid_ads_button_click - */ - -/** - * When the Onboarding is completed with Ads Setup. - * - * @event gla_onboarding_complete_ads_setup * @property {number} budget The budget for the campaign - * @property {number} audiences The targeted audiences for the campaign + * @property {string} audiences The targeted audiences for the campaign */ /** @@ -72,7 +65,6 @@ const ACTION_SKIP = 'skip-ads'; * @fires gla_onboarding_open_paid_ads_setup_button_click * @fires gla_onboarding_complete_with_paid_ads_button_click * @fires gla_onboarding_complete_button_click - * @fires gla_onboarding_complete_ads_setup */ export default function SetupPaidAds() { const adminUrl = useAdminUrl(); @@ -110,11 +102,6 @@ export default function SetupPaidAds() { ); } - recordEvent( 'gla_onboarding_complete_ads_setup', { - budget: paidAds.amount, - audiences: paidAds.countryCodes.join( ',' ), - } ); - // Force reload WC admin page to initiate the relevant dependencies of the Dashboard page. const query = { guide: GUIDE_NAMES.SUBMISSION_SUCCESS }; window.location.href = adminUrl + getProductFeedUrl( query ); @@ -222,6 +209,10 @@ export default function SetupPaidAds() { disabled={ disabledComplete } onClick={ handleCompleteClick } eventName="gla_onboarding_complete_with_paid_ads_button_click" + eventProps={ { + budget: paidAds.amount, + audiences: paidAds.countryCodes.join( ',' ), + } } /> diff --git a/src/Tracking/README.md b/src/Tracking/README.md index bc7ebc3556..b8104759e5 100644 --- a/src/Tracking/README.md +++ b/src/Tracking/README.md @@ -571,17 +571,7 @@ A modal is open - [`ReviewRequest`](../../js/src/product-feed/review-request/index.js#L31) with `context: REQUEST_REVIEW` - [`SubmissionSuccessGuide`](../../js/src/product-feed/submission-success-guide/index.js#L155) with `context: GUIDE_NAMES.SUBMISSION_SUCCESS` -### [`gla_onboarding_complete_ads_setup`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L46) -When the Onboarding is completed with Ads Setup. -#### Properties -| name | type | description | -| ---- | ---- | ----------- | -`budget` | `number` | The budget for the campaign -`audiences` | `number` | The targeted audiences for the campaign -#### Emitters -- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L77) - -### [`gla_onboarding_complete_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L54) +### [`gla_onboarding_complete_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L47) Clicking on the skip paid ads button to complete the onboarding flow. The 'unknown' value of properties may means: - the paid ads setup is not opened @@ -595,17 +585,22 @@ Clicking on the skip paid ads button to complete the onboarding flow. `billing_method_status` | `string` | aaa, The status of billing method of merchant's Google Ads addcount e.g. 'unknown', 'pending', 'approved', 'cancelled' `campaign_form_validation` | `string` | Whether the entered paid campaign form data are valid, e.g. 'unknown', 'valid', 'invalid' #### Emitters -- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L77) +- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L69) -### [`gla_onboarding_complete_with_paid_ads_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L40) +### [`gla_onboarding_complete_with_paid_ads_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L39) Clicking on the "Complete setup" button to complete the onboarding flow with paid ads. +#### Properties +| name | type | description | +| ---- | ---- | ----------- | +`budget` | `number` | The budget for the campaign +`audiences` | `string` | The targeted audiences for the campaign #### Emitters -- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L77) +- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L69) -### [`gla_onboarding_open_paid_ads_setup_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L34) +### [`gla_onboarding_open_paid_ads_setup_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L33) Clicking on the "Create a paid ad campaign" button to open the paid ads setup in the onboarding flow. #### Emitters -- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L77) +- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L69) ### [`gla_paid_campaign_step`](../../js/src/utils/recordEvent.js#L122) Triggered when moving to another step during creating/editing a campaign. From 721c0b267d5669794793cebefad3ab09e9a70cf6 Mon Sep 17 00:00:00 2001 From: Miguel Perez Pellicer <5908855+puntope@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:19:45 -0300 Subject: [PATCH 029/135] Prevent undefined country codes --- js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js b/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js index a28a7b78ab..634a134d5e 100644 --- a/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js +++ b/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js @@ -211,7 +211,7 @@ export default function SetupPaidAds() { eventName="gla_onboarding_complete_with_paid_ads_button_click" eventProps={ { budget: paidAds.amount, - audiences: paidAds.countryCodes.join( ',' ), + audiences: paidAds.countryCodes?.join( ',' ), } } /> From abf46d0f78730bf31fafe7e9b4f990d0992d4e99 Mon Sep 17 00:00:00 2001 From: Eason Su Date: Wed, 13 Dec 2023 16:06:13 +0800 Subject: [PATCH 030/135] Change the onboarding to require a connected Google Ads account and make its setup card always visible. --- js/src/hooks/useGoogleAdsAccount.js | 11 ++++++++++ .../setup-paid-ads/paid-ads-setup-sections.js | 22 +++++++++---------- .../setup-paid-ads/setup-paid-ads.js | 15 ++++++++----- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/js/src/hooks/useGoogleAdsAccount.js b/js/src/hooks/useGoogleAdsAccount.js index 9760ce87c8..16db5002f1 100644 --- a/js/src/hooks/useGoogleAdsAccount.js +++ b/js/src/hooks/useGoogleAdsAccount.js @@ -9,6 +9,7 @@ import { useCallback } from '@wordpress/element'; */ import { STORE_KEY } from '.~/data/constants'; import { useAppDispatch } from '.~/data'; +import { GOOGLE_ADS_ACCOUNT_STATUS } from '.~/constants'; import useGoogleAccount from './useGoogleAccount'; const googleAdsAccountSelector = 'getGoogleAdsAccount'; @@ -36,6 +37,15 @@ const useGoogleAdsAccount = () => { googleAdsAccountSelector ); + // The "incomplete" status means there is a connected account but billing is not yet set + // so it's considered as `true`. + // The main reason for not using a naming like `isGoogleAdsConnected` here is to make + // a slight distinction from the "connected" status. + const hasGoogleAdsConnection = [ + GOOGLE_ADS_ACCOUNT_STATUS.CONNECTED, + GOOGLE_ADS_ACCOUNT_STATUS.INCOMPLETE, + ].includes( acc?.status ); + return { googleAdsAccount: acc, isResolving: isResolvingGoogleAdsAccount, @@ -43,6 +53,7 @@ const useGoogleAdsAccount = () => { hasFinishedResolution: selector.hasFinishedResolution( googleAdsAccountSelector ), + hasGoogleAdsConnection, }; }, [ google, isResolving, refetchGoogleAdsAccount ] diff --git a/js/src/setup-mc/setup-stepper/setup-paid-ads/paid-ads-setup-sections.js b/js/src/setup-mc/setup-stepper/setup-paid-ads/paid-ads-setup-sections.js index f29fa2ff7a..86c3739bf7 100644 --- a/js/src/setup-mc/setup-stepper/setup-paid-ads/paid-ads-setup-sections.js +++ b/js/src/setup-mc/setup-stepper/setup-paid-ads/paid-ads-setup-sections.js @@ -11,16 +11,14 @@ import { Form } from '@woocommerce/components'; import useGoogleAdsAccount from '.~/hooks/useGoogleAdsAccount'; import useTargetAudienceFinalCountryCodes from '.~/hooks/useTargetAudienceFinalCountryCodes'; import useGoogleAdsAccountBillingStatus from '.~/hooks/useGoogleAdsAccountBillingStatus'; -import GoogleAdsAccountSection from './google-ads-account-section'; import AudienceSection from '.~/components/paid-ads/audience-section'; import BudgetSection from '.~/components/paid-ads/budget-section'; import BillingCard from '.~/components/paid-ads/billing-card'; +import SpinnerCard from '.~/components/spinner-card'; +import Section from '.~/wcdl/section'; import validateCampaign from '.~/components/paid-ads/validateCampaign'; import clientSession from './clientSession'; -import { - GOOGLE_ADS_ACCOUNT_STATUS, - GOOGLE_ADS_BILLING_STATUS, -} from '.~/constants'; +import { GOOGLE_ADS_BILLING_STATUS } from '.~/constants'; /** * @typedef { import(".~/data/actions").CountryCode } CountryCode @@ -77,7 +75,7 @@ function resolveInitialPaidAds( paidAds, targetAudience ) { * @param {(onStatesReceived: PaidAdsData)=>void} props.onStatesReceived Callback to receive the data for setting up paid ads when initial and also when the audience, budget, and billing are updated. */ export default function PaidAdsSetupSections( { onStatesReceived } ) { - const { googleAdsAccount } = useGoogleAdsAccount(); + const { hasGoogleAdsConnection } = useGoogleAdsAccount(); const { data: targetAudience } = useTargetAudienceFinalCountryCodes(); const { billingStatus } = useGoogleAdsAccountBillingStatus(); @@ -135,7 +133,11 @@ export default function PaidAdsSetupSections( { onStatesReceived } ) { }, [ targetAudience ] ); if ( ! targetAudience || ! billingStatus ) { - return ; + return ( +

+ +
+ ); } const initialValues = { @@ -153,16 +155,12 @@ export default function PaidAdsSetupSections( { onStatesReceived } ) { > { ( formProps ) => { const { countryCodes } = formProps.values; - const disabledAudience = ! [ - GOOGLE_ADS_ACCOUNT_STATUS.CONNECTED, - GOOGLE_ADS_ACCOUNT_STATUS.INCOMPLETE, - ].includes( googleAdsAccount?.status ); + const disabledAudience = ! hasGoogleAdsConnection; const disabledBudget = disabledAudience || countryCodes.length === 0; return ( <> - clientSession.getShowPaidAdsSetup( false ) @@ -123,31 +126,32 @@ export default function SetupPaidAds() { function createSkipButton( text ) { const eventProps = { opened_paid_ads_setup: 'no', - google_ads_account_status: 'unknown', + google_ads_account_status: googleAdsAccount?.status, billing_method_status: 'unknown', campaign_form_validation: 'unknown', }; if ( showPaidAdsSetup ) { const selector = select( STORE_KEY ); - const account = selector.getGoogleAdsAccount(); const billing = selector.getGoogleAdsAccountBillingStatus(); merge( eventProps, { opened_paid_ads_setup: 'yes', - google_ads_account_status: account?.status, billing_method_status: billing?.status, campaign_form_validation: paidAds.isValid ? 'valid' : 'invalid', } ); } + const disabledSkip = + completing === ACTION_COMPLETE || ! hasGoogleAdsConnection; + return ( + Date: Wed, 13 Dec 2023 16:08:18 +0800 Subject: [PATCH 031/135] Hide the content about the ad budget in the Boost card before a Google Ads account is connected. --- .../campaign-preview/mockup-search.js | 2 +- .../paid-ads-features-section.js | 41 +++++++++++-------- .../setup-paid-ads/setup-paid-ads.js | 5 ++- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/js/src/components/paid-ads/campaign-preview/mockup-search.js b/js/src/components/paid-ads/campaign-preview/mockup-search.js index bdf2b04d2b..fb1e013439 100644 --- a/js/src/components/paid-ads/campaign-preview/mockup-search.js +++ b/js/src/components/paid-ads/campaign-preview/mockup-search.js @@ -48,7 +48,7 @@ export default function MockupSearch( { product } ) { - +
diff --git a/js/src/setup-mc/setup-stepper/setup-paid-ads/paid-ads-features-section.js b/js/src/setup-mc/setup-stepper/setup-paid-ads/paid-ads-features-section.js index 14099026e6..fe3330df4c 100644 --- a/js/src/setup-mc/setup-stepper/setup-paid-ads/paid-ads-features-section.js +++ b/js/src/setup-mc/setup-stepper/setup-paid-ads/paid-ads-features-section.js @@ -15,7 +15,7 @@ import AppDocumentationLink from '.~/components/app-documentation-link'; import CampaignPreview from '.~/components/paid-ads/campaign-preview'; import './paid-ads-features-section.scss'; -function FeatureList() { +function FeatureList( { hideBudgetContent } ) { const featuresItems = [ { Icon: GridiconCheckmark, @@ -24,22 +24,27 @@ function FeatureList() { 'google-listings-and-ads' ), }, - { - Icon: GridiconCheckmark, - content: __( - 'Set a daily budget, and only pay when someone clicks.', - 'google-listings-and-ads' - ), - }, - { - Icon: GridiconGift, - content: __( - 'Claim $500 in ads credit when you spend your first $500 with Google Ads. Terms and conditions apply.', - 'google-listings-and-ads' - ), - }, ]; + if ( ! hideBudgetContent ) { + featuresItems.push( + { + Icon: GridiconCheckmark, + content: __( + 'Set a daily budget, and only pay when someone clicks.', + 'google-listings-and-ads' + ), + }, + { + Icon: GridiconGift, + content: __( + 'Claim $500 in ads credit when you spend your first $500 with Google Ads. Terms and conditions apply.', + 'google-listings-and-ads' + ), + } + ); + } + return (
{ featuresItems.map( ( { Icon, content }, idx ) => ( @@ -61,11 +66,13 @@ function FeatureList() { * for the next actions: skip or continue the paid ads setup. * * @param {Object} props React props. + * @param {boolean} props.hideBudgetContent Whether to hide the content about the ad budget. * @param {boolean} props.hideFooterButtons Whether to hide the buttons at the card footer. * @param {JSX.Element} props.skipButton Button to skip paid ads setup. * @param {JSX.Element} props.continueButton Button to continue paid ads setup. */ export default function PaidAdsFeaturesSection( { + hideBudgetContent, hideFooterButtons, skipButton, continueButton, @@ -120,7 +127,9 @@ export default function PaidAdsFeaturesSection( { 'google-listings-and-ads' ) }
- + { __( 'Source: Google Internal Data, July 2020', diff --git a/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js b/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js index 42ac698057..b576527af8 100644 --- a/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js +++ b/js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js @@ -174,7 +174,10 @@ export default function SetupPaidAds() { Date: Wed, 13 Dec 2023 16:13:21 +0800 Subject: [PATCH 032/135] Update tracking README. --- src/Tracking/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Tracking/README.md b/src/Tracking/README.md index b8104759e5..2be5fc3674 100644 --- a/src/Tracking/README.md +++ b/src/Tracking/README.md @@ -571,7 +571,7 @@ A modal is open - [`ReviewRequest`](../../js/src/product-feed/review-request/index.js#L31) with `context: REQUEST_REVIEW` - [`SubmissionSuccessGuide`](../../js/src/product-feed/submission-success-guide/index.js#L155) with `context: GUIDE_NAMES.SUBMISSION_SUCCESS` -### [`gla_onboarding_complete_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L47) +### [`gla_onboarding_complete_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L49) Clicking on the skip paid ads button to complete the onboarding flow. The 'unknown' value of properties may means: - the paid ads setup is not opened @@ -581,13 +581,13 @@ Clicking on the skip paid ads button to complete the onboarding flow. | name | type | description | | ---- | ---- | ----------- | `opened_paid_ads_setup` | `string` | Whether the paid ads setup is opened, e.g. 'yes', 'no' -`google_ads_account_status` | `string` | The connection status of merchant's Google Ads addcount, e.g. 'unknown', 'connected', 'disconnected', 'incomplete' +`google_ads_account_status` | `string` | The connection status of merchant's Google Ads addcount, e.g. 'connected', 'disconnected', 'incomplete' `billing_method_status` | `string` | aaa, The status of billing method of merchant's Google Ads addcount e.g. 'unknown', 'pending', 'approved', 'cancelled' `campaign_form_validation` | `string` | Whether the entered paid campaign form data are valid, e.g. 'unknown', 'valid', 'invalid' #### Emitters -- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L69) +- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L71) -### [`gla_onboarding_complete_with_paid_ads_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L39) +### [`gla_onboarding_complete_with_paid_ads_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L41) Clicking on the "Complete setup" button to complete the onboarding flow with paid ads. #### Properties | name | type | description | @@ -595,12 +595,12 @@ Clicking on the "Complete setup" button to complete the onboarding flow with pai `budget` | `number` | The budget for the campaign `audiences` | `string` | The targeted audiences for the campaign #### Emitters -- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L69) +- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L71) -### [`gla_onboarding_open_paid_ads_setup_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L33) +### [`gla_onboarding_open_paid_ads_setup_button_click`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L35) Clicking on the "Create a paid ad campaign" button to open the paid ads setup in the onboarding flow. #### Emitters -- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L69) +- [`exports`](../../js/src/setup-mc/setup-stepper/setup-paid-ads/setup-paid-ads.js#L71) ### [`gla_paid_campaign_step`](../../js/src/utils/recordEvent.js#L122) Triggered when moving to another step during creating/editing a campaign. From 0453a6d1b8644f182d983a1e4948ee7adc3aca18 Mon Sep 17 00:00:00 2001 From: martynmjones Date: Tue, 5 Dec 2023 19:08:48 +0000 Subject: [PATCH 033/135] Update budget recommendation text --- tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js | 2 +- tests/e2e/utils/pages/setup-ads/setup-budget.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js index cbea1c7d23..8e0e64b5b5 100644 --- a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js +++ b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js @@ -360,7 +360,7 @@ test.describe( 'Set up Ads account', () => { test( 'Budget Recommendation', async () => { await expect( - page.getByText( 'set a daily budget of 5 to 15 USD' ) + page.getByText( 'set a daily budget of 15 USD' ) ).toBeVisible(); } ); } ); diff --git a/tests/e2e/utils/pages/setup-ads/setup-budget.js b/tests/e2e/utils/pages/setup-ads/setup-budget.js index 54ec0ab8eb..355aae1029 100644 --- a/tests/e2e/utils/pages/setup-ads/setup-budget.js +++ b/tests/e2e/utils/pages/setup-ads/setup-budget.js @@ -92,7 +92,7 @@ export default class SetupBudget extends MockRequests { * @return {string} The budget recommendation range. */ extractBudgetRecommendationRange( text ) { - const match = text.match( /set a daily budget of (\d+ to \d+)/ ); + const match = text.match( /set a daily budget of (\d+)/ ); if ( match ) { return match[ 1 ]; } From 138b25615891395c3e1995a8a14fdc2ff30317ef Mon Sep 17 00:00:00 2001 From: Eason Su Date: Thu, 14 Dec 2023 16:48:29 +0800 Subject: [PATCH 034/135] Fix the budget recommendation E2E tests for PR #2153 after cherry-picking PR #2174. Ref: - https://github.com/woocommerce/google-listings-and-ads/pull/2153 - https://github.com/woocommerce/google-listings-and-ads/pull/2174#pullrequestreview-1771727538 --- .../add-paid-campaigns/add-paid-campaigns.test.js | 10 ---------- .../specs/setup-mc/step-4-complete-campaign.test.js | 8 ++++---- tests/e2e/utils/mock-requests.js | 13 ------------- tests/e2e/utils/pages/setup-ads/setup-budget.js | 6 +++--- 4 files changed, 7 insertions(+), 30 deletions(-) diff --git a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js index 8e0e64b5b5..a7b1cd56b1 100644 --- a/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js +++ b/tests/e2e/specs/add-paid-campaigns/add-paid-campaigns.test.js @@ -248,16 +248,6 @@ test.describe( 'Set up Ads account', () => { test.describe( 'Create your paid campaign', () => { test.beforeAll( async () => { setupBudgetPage = new SetupBudgetPage( page ); - await setupBudgetPage.fulfillBudgetRecommendation( { - currency: 'USD', - recommendations: [ - { - country: 'US', - daily_budget_low: 5, - daily_budget_high: 15, - }, - ], - } ); } ); test( 'Continue to create paid campaign', async () => { diff --git a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js index c34ac1a1c4..0046273e56 100644 --- a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js +++ b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js @@ -423,13 +423,13 @@ test.describe( 'Complete your campaign', () => { await expect( treeSelectMenu ).not.toBeVisible(); } ); - test( 'should see the budget recommendation range changed, and see the budget recommendation request is triggered when changing the ads audience', async () => { + test( 'should see the budget recommendation value changed, and see the budget recommendation request is triggered when changing the ads audience', async () => { let textContent = await setupBudgetPage .getBudgetRecommendationTextRow() .textContent(); const textBeforeRemoveCountry = - setupBudgetPage.extractBudgetRecommendationRange( + setupBudgetPage.extractBudgetRecommendationValue( textContent ); @@ -438,7 +438,7 @@ test.describe( 'Complete your campaign', () => { await removeCountryFromSearchBox( page, - 'United States (US)' + 'United Kingdom (UK)' ); await responsePromise; @@ -448,7 +448,7 @@ test.describe( 'Complete your campaign', () => { .textContent(); const textAfterRemoveCountry = - setupBudgetPage.extractBudgetRecommendationRange( + setupBudgetPage.extractBudgetRecommendationValue( textContent ); diff --git a/tests/e2e/utils/mock-requests.js b/tests/e2e/utils/mock-requests.js index 09a61c4c48..73d2e601bd 100644 --- a/tests/e2e/utils/mock-requests.js +++ b/tests/e2e/utils/mock-requests.js @@ -222,19 +222,6 @@ export default class MockRequests { await this.fulfillRequest( /\/wc\/gla\/ads\/accounts\b/, payload ); } - /** - * Fulfill the Budget Recommendation request. - * - * @param {Object} payload - * @return {Promise} - */ - async fulfillBudgetRecommendation( payload ) { - await this.fulfillRequest( - /\/wc\/gla\/ads\/campaigns\/budget-recommendation\b/, - payload - ); - } - /** * Fulfill the Sync Settings Connection request. * diff --git a/tests/e2e/utils/pages/setup-ads/setup-budget.js b/tests/e2e/utils/pages/setup-ads/setup-budget.js index 355aae1029..dca6843f64 100644 --- a/tests/e2e/utils/pages/setup-ads/setup-budget.js +++ b/tests/e2e/utils/pages/setup-ads/setup-budget.js @@ -85,13 +85,13 @@ export default class SetupBudget extends MockRequests { } /** - * Extract budget recommendation range. + * Extract budget recommendation value. * * @param {string} text * - * @return {string} The budget recommendation range. + * @return {string} The budget recommendation value. */ - extractBudgetRecommendationRange( text ) { + extractBudgetRecommendationValue( text ) { const match = text.match( /set a daily budget of (\d+)/ ); if ( match ) { return match[ 1 ]; From cc8fe7be78aa31f500bf5497b0573e538a8a0998 Mon Sep 17 00:00:00 2001 From: Eason Su Date: Thu, 14 Dec 2023 18:14:52 +0800 Subject: [PATCH 035/135] Add more utils to mock requests for E2E tests. --- tests/e2e/utils/mock-requests.js | 36 ++++++++++++++++ .../pages/setup-ads/setup-ads-accounts.js | 43 +++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/tests/e2e/utils/mock-requests.js b/tests/e2e/utils/mock-requests.js index 73d2e601bd..5ee29a943a 100644 --- a/tests/e2e/utils/mock-requests.js +++ b/tests/e2e/utils/mock-requests.js @@ -296,6 +296,42 @@ export default class MockRequests { ); } + /** + * Fulfill the MC account issues request. + * + * @param {Object} payload + * @return {Promise} + */ + async fulfillAccountIssuesRequest( payload ) { + await this.fulfillRequest( + /\/wc\/gla\/mc\/issues\/account\b/, + payload + ); + } + + /** + * Fulfill the MC product issues request. + * + * @param {Object} payload + * @return {Promise} + */ + async fulfillProductIssuesRequest( payload ) { + await this.fulfillRequest( + /\/wc\/gla\/mc\/issues\/product\b/, + payload + ); + } + + /** + * Fulfill the MC review request. + * + * @param {Object} payload + * @return {Promise} + */ + async fulfillMCReview( payload ) { + await this.fulfillRequest( /\/wc\/gla\/mc\/review\b/, payload ); + } + /** * Fulfill product statistics request. * diff --git a/tests/e2e/utils/pages/setup-ads/setup-ads-accounts.js b/tests/e2e/utils/pages/setup-ads/setup-ads-accounts.js index 5e18565506..fb41f64dcd 100644 --- a/tests/e2e/utils/pages/setup-ads/setup-ads-accounts.js +++ b/tests/e2e/utils/pages/setup-ads/setup-ads-accounts.js @@ -117,6 +117,49 @@ export default class SetupAdsAccount extends MockRequests { await this.getAdsAccountSelect().selectOption( accountNumber ); } + /** + * Mock Google Ads account as not yet connected. + * + * @return {Promise} + */ + async mockAdsAccountDisconnected() { + await this.fulfillAdsConnection( { + id: 0, + currency: null, + symbol: 'NT$', + status: 'disconnected', + } ); + } + + /** + * Mock Google Ads account as connected but its billing setup is incomplete. + * + * @return {Promise} + */ + async mockAdsAccountIncomplete() { + await this.fulfillAdsConnection( { + id: 12345, + currency: 'TWD', + symbol: 'NT$', + status: 'incomplete', + } ); + } + + /** + * Mock Google Ads account as connected. + * + * @param {number} [id=12345] + * @return {Promise} + */ + async mockAdsAccountConnected( id = 12345 ) { + await this.fulfillAdsConnection( { + id, + currency: 'TWD', + symbol: 'NT$', + status: 'connected', + } ); + } + /** * Mock the Ads accounts response. * From 2d976e3f60039e6a07c0cf15ac44fc7f5dc9a5bc Mon Sep 17 00:00:00 2001 From: Eason Su Date: Thu, 14 Dec 2023 18:18:19 +0800 Subject: [PATCH 036/135] Adjust E2E tests to reflect the change of requiring Google Ads connection in step 4 of the onboarding. --- .../setup-mc/step-4-complete-campaign.test.js | 347 +++++++++++------- .../setup-mc/step-4-complete-campaign.js | 12 +- 2 files changed, 225 insertions(+), 134 deletions(-) diff --git a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js index 0046273e56..4f9594f7f2 100644 --- a/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js +++ b/tests/e2e/specs/setup-mc/step-4-complete-campaign.test.js @@ -61,6 +61,12 @@ test.describe( 'Complete your campaign', () => { // Mock Merchant Center as connected completeCampaign.mockMCConnected(), + // Mock Google Ads as not yet connected. + setupAdsAccountPage.mockAdsAccountDisconnected(), + + // Mock there is no existing Google Ads account. + setupAdsAccountPage.mockAdsAccountsResponse( [] ), + // Mock MC step as paid_ads completeCampaign.mockMCSetup( 'incomplete', 'paid_ads' ), @@ -79,6 +85,40 @@ test.describe( 'Complete your campaign', () => { completeCampaign.fulfillSyncableProductsCountRequest( { count: 1024, } ), + + // The following mocks are requests will happen after completing the onboarding + completeCampaign.mockSuccessfulSettingsSyncRequest(), + + completeCampaign.fulfillProductStatisticsRequest( { + timestamp: 1695011644, + statistics: { + active: 0, + expiring: 0, + pending: 0, + disapproved: 0, + not_synced: 1137, + }, + scheduled_sync: 1, + } ), + + completeCampaign.fulfillAccountIssuesRequest( { + issues: [], + page: 1, + total: 0, + } ), + + completeCampaign.fulfillProductIssuesRequest( { + issues: [], + page: 1, + total: 0, + } ), + + completeCampaign.fulfillMCReview( { + cooldown: 0, + issues: [], + reviewEligibleRegions: [], + status: 'ONBOARDING', + } ), ] ); await completeCampaign.goto(); @@ -127,124 +167,63 @@ test.describe( 'Complete your campaign', () => { } ); } ); - test.describe( 'Click "Skip this step for now"', () => { - test.beforeAll( async () => { - await Promise.all( [ - // Mock settings sync request - completeCampaign.mockSuccessfulSettingsSyncRequest(), - - // Mock product statistics request - completeCampaign.fulfillProductStatisticsRequest( { - timestamp: 1695011644, - statistics: { - active: 0, - expiring: 0, - pending: 0, - disapproved: 0, - not_synced: 1137, - }, - scheduled_sync: 1, - } ), - ] ); - await completeCampaign.clickSkipStepButton(); - } ); - - test( 'should see the setup success modal', async () => { - const setupSuccessModal = page - .locator( '.components-modal__content' ) - .filter( { - hasText: - 'You’ve successfully set up Google Listings & Ads!', - } ); - await expect( setupSuccessModal ).toBeVisible(); - } ); - - test( 'should see the url contains product-feed', async () => { - expect( page.url() ).toMatch( /path=%2Fgoogle%2Fproduct-feed/ ); - } ); - } ); - - test.describe( 'Set up paid ads', () => { - test.beforeAll( async () => { - await Promise.all( [ - // Mock settings sync request - completeCampaign.mockSuccessfulSettingsSyncRequest(), - - // Mock product statistics request - completeCampaign.fulfillProductStatisticsRequest( { - timestamp: 1695011644, - statistics: { - active: 0, - expiring: 0, - pending: 0, - disapproved: 0, - not_synced: 1137, - }, - scheduled_sync: 1, - } ), - ] ); - await completeCampaign.goto(); - } ); - - test( 'should see the "Create a paid ad campaign" button is enabled', async () => { - const button = completeCampaign.getCreatePaidAdButton(); - await expect( button ).toBeVisible(); - await expect( button ).toBeEnabled(); - } ); - - test.describe( 'Click "Create a paid ad campaign" button', () => { - test.beforeAll( async () => { - await completeCampaign.clickCreatePaidAdButton(); - await setupAdsAccountPage.mockAdsAccountsResponse( [] ); + test.describe( 'Google Ads', () => { + test.describe( 'Google Ads section', () => { + test.beforeEach( async () => { + await completeCampaign.goto(); } ); - test( 'should see "Complete setup" button is disabled', async () => { - const completeSetupButton = - completeCampaign.getCompleteSetupButton(); - await expect( completeSetupButton ).toBeVisible(); - await expect( completeSetupButton ).toBeDisabled(); + test( 'should see Google Ads section', async () => { + const section = completeCampaign.getAdsAccountSection(); + await expect( section ).toBeVisible(); } ); - test( 'should see "Skip paid ads creation" button is enabled', async () => { - const skipPaidAdsCreationButton = - completeCampaign.getSkipPaidAdsCreationButton(); - await expect( skipPaidAdsCreationButton ).toBeVisible(); - await expect( skipPaidAdsCreationButton ).toBeEnabled(); - } ); - - test( 'should see "Google Ads" section is enabled', async () => { - const googleAdsSection = - completeCampaign.getAdsAccountSection(); - await expect( googleAdsSection ).toBeVisible(); + test( 'should only see non-budget related items and no footer buttons in the Features section when not yet connected', async () => { + const section = completeCampaign.getPaidAdsFeaturesSection(); + const items = section.locator( + '.gla-paid-ads-features-section__feature-list > div' + ); + await expect( items ).toHaveCount( 1 ); + await expect( items ).toContainText( 'Promote your products' ); - // Cannot use toBeEnabled() because
is not a native control element - // such as