Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add notice about webhooks using the legacy REST API #40866

Merged
merged 8 commits into from Oct 24, 2023
4 changes: 4 additions & 0 deletions plugins/woocommerce/changelog/pr-40866
@@ -0,0 +1,4 @@
Significance: minor
Type: add

Add notices about the webhooks using legacy REST API payload going unsupported in WooCommerce 9.0
72 changes: 46 additions & 26 deletions plugins/woocommerce/includes/admin/class-wc-admin-notices.php
Expand Up @@ -9,6 +9,7 @@
use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Internal\Traits\AccessiblePrivateMethods;
use Automattic\WooCommerce\Internal\Utilities\Users;
use Automattic\WooCommerce\Internal\Utilities\WebhookUtil;

defined( 'ABSPATH' ) || exit;

Expand Down Expand Up @@ -125,53 +126,72 @@ public static function reset_admin_notices() {
// phpcs:disable Generic.Commenting.Todo.TaskFound

/**
* Add an admin notice about the removal of the Legacy REST API if the said API is enabled.
* Add an admin notice about the removal of the Legacy REST API if the said API is enabled,
* and a notice about soon to be unsupported webhooks with Legacy API payload if at least one of these exist.
*
* TODO: Change this method in WooCommerce 9.0 so that it checks if the Legacy REST API extension is installed, and if not, it points to the extension URL in the WordPress plugins directory.
*/
private static function maybe_add_legacy_api_removal_notice() {
if ( ! self::must_show_legacy_api_removal_notice() ) {
if ( is_plugin_active( 'woocommerce-legacy-rest-api/woocommerce-legacy-rest-api.php' ) ) {
return;
}

self::add_custom_notice(
'legacy_api_removed_in_woo_90',
sprintf(
'%s%s',
if ( 'yes' === get_option( 'woocommerce_api_enabled' ) ) {
self::add_custom_notice(
'legacy_api_removed_in_woo_90',
sprintf(
'<h4>%s</h4>',
esc_html__( 'The WooCommerce Legacy REST API will be removed soon', 'woocommerce' )
),
'%s%s',
sprintf(
'<h4>%s</h4>',
esc_html__( 'The WooCommerce Legacy REST API will be removed soon', 'woocommerce' )
),
sprintf(
// translators: Placeholders are URLs.
wpautop( wp_kses_data( __( 'The WooCommerce Legacy REST API, <a href="%1$s">currently enabled in this site</a>, will be removed in WooCommerce 9.0. A separate WooCommerce extension will be available to keep it enabled. <b><a target=”_blank” href="%2$s">Learn more about this change.</a></b>', 'woocommerce' ) ) ),
admin_url( 'admin.php?page=wc-settings&tab=advanced&section=legacy_api' ),
'https://developer.woocommerce.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/'
)
)
);
}

if ( wc_get_container()->get( WebhookUtil::class )->get_legacy_webhooks_count() > 0 ) {
self::add_custom_notice(
'legacy_webhooks_unsupported_in_woo_90',
sprintf(
'%s%s',
sprintf(
'<h4>%s</h4>',
esc_html__( 'The WooCommerce webhooks with Legacy REST API payload will be unsupported soon', 'woocommerce' )
Konamiman marked this conversation as resolved.
Show resolved Hide resolved
),
sprintf(
// translators: Placeholders are URLs.
wpautop( wp_kses_data( __( 'The WooCommerce Legacy REST API, <a href="%1$s">currently enabled in this site</a>, will be removed in WooCommerce 9.0. A separate WooCommerce extension will be available to keep it enabled. <b><a target=”_blank” href="%2$s">Learn more about this change.</a></b>', 'woocommerce' ) ) ),
admin_url( 'admin.php?page=wc-settings&tab=advanced&section=legacy_api' ),
'https://developer.woocommerce.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/'
wpautop( wp_kses_data( __( 'The WooCommerce Legacy REST API will be removed in WooCommerce 9.0, and this will cause <a href="%1$s">the Legacy REST API payload webhooks currently existing in this site</a> to stop working. A separate WooCommerce extension will be available to keep the Legacy REST API enabled and these webhooks working, you can also edit these webhooks to use the current REST API to generate the payload. <b><a target=”_blank” href="%2$s">Learn more about this change.</a></b>', 'woocommerce' ) ) ),
Konamiman marked this conversation as resolved.
Show resolved Hide resolved
admin_url( 'admin.php?page=wc-settings&tab=advanced&section=webhooks&legacy=true' ),
'https://developer.woocommerce.com/2023/10/03/the-legacy-rest-api-will-move-to-a-dedicated-extension-in-woocommerce-9-0/'
)
)
)
);
);
}
}

/**
* Remove the admin notice about the removal of the Legacy REST API if the said API is disabled.
* Remove the admin notice about the removal of the Legacy REST API if the said API is disabled
* or if the Legacy REST API extension is installed, and remove the notice about Legacy webhooks
* if no such webhooks exist anymore or if the Legacy REST API extension is installed.
*
* TODO: Change this method in WooCommerce 9.0 so that the notice gets removed if the Legacy REST API extension is installed and active.
*/
private static function maybe_remove_legacy_api_removal_notice() {
if ( self::has_notice( 'legacy_api_removed_in_woo_90' ) && ! self::must_show_legacy_api_removal_notice() ) {
$plugin_is_active = is_plugin_active( 'woocommerce-legacy-rest-api/woocommerce-legacy-rest-api.php' );

if ( self::has_notice( 'legacy_api_removed_in_woo_90' ) && ( $plugin_is_active || 'yes' !== get_option( 'woocommerce_api_enabled' ) ) ) {
self::remove_notice( 'legacy_api_removed_in_woo_90' );
}
}

/**
* Is it needed to display the legacy API removal notice?
*
* TODO: Change or remove this method in WooCommerce 9.0 accordingly, depending on the changes to maybe_add/remove_legacy_api_removal_notice.
*
* @return bool True if the legacy API removal notice must be displayed.
*/
private static function must_show_legacy_api_removal_notice() {
return 'yes' === get_option( 'woocommerce_api_enabled' ) && ! is_plugin_active( 'woocommerce-legacy-rest-api/woocommerce-legacy-rest-api.php' );
if ( self::has_notice( 'legacy_webhooks_unsupported_in_woo_90' ) && ( $plugin_is_active || 0 === wc_get_container()->get( WebhookUtil::class )->get_legacy_webhooks_count() ) ) {
self::remove_notice( 'legacy_webhooks_unsupported_in_woo_90' );
}
}

// phpcs:enable Generic.Commenting.Todo.TaskFound
Expand Down
Expand Up @@ -6,6 +6,8 @@
* @version 3.3.0
*/

use Automattic\WooCommerce\Internal\Utilities\WebhookUtil;

defined( 'ABSPATH' ) || exit;

if ( ! class_exists( 'WP_List_Table' ) ) {
Expand Down Expand Up @@ -174,7 +176,8 @@ protected function get_views() {
$num_webhooks = $data_store->get_count_webhooks_by_status();
$total_webhooks = array_sum( (array) $num_webhooks );
$statuses = array_keys( wc_get_webhook_statuses() );
$class = empty( $_REQUEST['status'] ) ? ' class="current"' : ''; // WPCS: input var okay. CSRF ok.
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$class = empty( $_REQUEST['status'] ) && empty( $_REQUEST['legacy'] ) ? ' class="current"' : '';

/* translators: %s: count */
$status_links['all'] = "<a href='admin.php?page=wc-settings&amp;tab=advanced&amp;section=webhooks'$class>" . sprintf( _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_webhooks, 'posts', 'woocommerce' ), number_format_i18n( $total_webhooks ) ) . '</a>';
Expand All @@ -186,7 +189,8 @@ protected function get_views() {
continue;
}

if ( isset( $_REQUEST['status'] ) && sanitize_key( wp_unslash( $_REQUEST['status'] ) ) === $status_name ) { // WPCS: input var okay, CSRF ok.
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( isset( $_REQUEST['status'] ) && sanitize_key( wp_unslash( $_REQUEST['status'] ) ) === $status_name ) {
$class = ' class="current"';
}

Expand All @@ -195,6 +199,20 @@ protected function get_views() {
$status_links[ $status_name ] = "<a href='admin.php?page=wc-settings&amp;tab=advanced&amp;section=webhooks&amp;status=$status_name'$class>" . sprintf( translate_nooped_plural( $label, $num_webhooks[ $status_name ] ), number_format_i18n( $num_webhooks[ $status_name ] ) ) . '</a>';
}

$legacy_webhooks_count = wc_get_container()->get( WebhookUtil::class )->get_legacy_webhooks_count();
if ( $legacy_webhooks_count > 0 ) {
$class = '';

// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( 'true' === sanitize_key( wp_unslash( $_REQUEST['legacy'] ?? '' ) ) ) {
$class = ' class="current"';
}

$label = $this->get_status_label( __( 'Legacy', 'woocommerce' ), $legacy_webhooks_count );

$status_links['legacy'] = "<a href='admin.php?page=wc-settings&amp;tab=advanced&amp;section=webhooks&amp;legacy=true'$class>" . sprintf( translate_nooped_plural( $label, $legacy_webhooks_count ), number_format_i18n( $legacy_webhooks_count ) ) . '</a>';
}

return $status_links;
}

Expand Down Expand Up @@ -299,6 +317,10 @@ public function prepare_items() {

$args['paginate'] = true;

if ( 'true' === sanitize_key( wp_unslash( $_REQUEST['legacy'] ) ) ) {
$args['api_version'] = -1;
}

// Get the webhooks.
$data_store = WC_Data_Store::load( 'webhook' );
$webhooks = $data_store->search_webhooks( $args );
Expand Down
Expand Up @@ -283,6 +283,7 @@ public function search_webhooks( $args ) {
$date_created = '';
$date_modified = '';
$user_id = '';
$api_version = '';

if ( ! empty( $args['include'] ) ) {
$args['include'] = implode( ',', wp_parse_id_list( $args['include'] ) );
Expand Down Expand Up @@ -312,6 +313,11 @@ public function search_webhooks( $args ) {
$date_modified = "AND `date_modified_gmt` BETWEEN STR_TO_DATE('" . esc_sql( $args['modified_after'] ) . "', '%Y-%m-%d %H:%i:%s') and STR_TO_DATE('" . esc_sql( $args['modified_before'] ) . "', '%Y-%m-%d %H:%i:%s')";
}

$api_version_value = $args['api_version'] ?? null;
if ( is_numeric( $api_version_value ) ) {
$api_version = 'AND `api_version`=' . esc_sql( $api_version_value );
}

// Check for cache.
$cache_key = WC_Cache_Helper::get_cache_prefix( 'webhooks' ) . 'search_webhooks' . md5( implode( ',', $args ) );
$cache_value = wp_cache_get( $cache_key, 'webhook_search_results' );
Expand All @@ -331,6 +337,7 @@ public function search_webhooks( $args ) {
{$exclude}
{$date_created}
{$date_modified}
{$api_version}
{$user_id}
{$order}
{$limit}
Expand Down
20 changes: 20 additions & 0 deletions plugins/woocommerce/src/Internal/Utilities/WebhookUtil.php
Expand Up @@ -6,6 +6,7 @@
namespace Automattic\WooCommerce\Internal\Utilities;

use Automattic\WooCommerce\Internal\Traits\AccessiblePrivateMethods;
use WC_Cache_Helper;

/**
* Class with utility methods for dealing with webhooks.
Expand Down Expand Up @@ -133,4 +134,23 @@ private function get_webhook_ids_for_user( int $user_id ): array {
)
);
}

/**
* Gets the count of webhooks that are configured to use the Legacy REST API to compose their payloads.
*
* @return int
*/
public function get_legacy_webhooks_count(): int {
global $wpdb;

$cache_key = WC_Cache_Helper::get_cache_prefix( 'webhooks' ) . 'legacy_count';
$count = wp_cache_get( $cache_key, 'webhooks' );

if ( false === $count ) {
$count = absint( $wpdb->get_var( "SELECT count( webhook_id ) FROM {$wpdb->prefix}wc_webhooks WHERE `api_version` < 1;" ) );
wp_cache_add( $cache_key, $count, 'webhooks' );
Konamiman marked this conversation as resolved.
Show resolved Hide resolved
}

return $count;
}
}