diff --git a/.changeset/witty-falcons-type.md b/.changeset/witty-falcons-type.md
new file mode 100644
index 00000000..b86ea2a5
--- /dev/null
+++ b/.changeset/witty-falcons-type.md
@@ -0,0 +1,6 @@
+---
+"@wpengine/wp-graphql-content-blocks": minor
+---
+
+Replaced old plugin service to use the WPE updater service for checking for updates. The new API endpoint will be https://wpe-plugin-updates.wpengine.com/wp-graphql-content-blocks/info.json
+
diff --git a/includes/PluginUpdater/UpdateCallbacks.php b/includes/PluginUpdater/UpdateCallbacks.php
deleted file mode 100644
index 1aed0449..00000000
--- a/includes/PluginUpdater/UpdateCallbacks.php
+++ /dev/null
@@ -1,183 +0,0 @@
-requires_at_least ) || empty( $response->version ) ) {
- return $data;
- }
-
- $response->slug = 'wp-graphql-content-blocks';
- $current_plugin_data = \get_plugin_data( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE );
- $meets_wp_req = version_compare( get_bloginfo( 'version' ), $response->requires_at_least, '>=' );
-
- // Only update the response if there's a newer version, otherwise WP shows an update notice for the same version.
- if ( $meets_wp_req && version_compare( $current_plugin_data['Version'], $response->version, '<' ) ) {
- $response->plugin = plugin_basename( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE );
- $data->response[ WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_PATH ] = $response;
- }
-
- return $data;
-}
-
-add_filter( 'plugins_api', __NAMESPACE__ . '\custom_plugin_api_request', 10, 3 );
-/**
- * Callback for WordPress 'plugins_api' filter.
- *
- * Return a custom response for this plugin from the custom endpoint.
- *
- * @link https://developer.wordpress.org/reference/hooks/plugins_api/
- *
- * @param false|object|array $api The result object or array. Default false.
- * @param string $action The type of information being requested from the Plugin Installation API.
- * @param object $args Plugin API arguments.
- *
- * @return false|object|array $response Plugin API arguments.
- */
-function custom_plugin_api_request( $api, $action, $args ) {
- // Bail if it's not our plugin.
- $plugin_slug = dirname( plugin_basename( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE ) );
-
- if ( empty( $args->slug ) || $plugin_slug !== $args->slug ) {
- return $api;
- }
-
- $response = get_plugin_data_from_wpe( $args );
- if ( empty( $response ) || is_wp_error( $response ) ) {
- return $api;
- }
-
- return $response;
-}
-
-add_action( 'admin_notices', __NAMESPACE__ . '\delegate_plugin_row_notice' );
-/**
- * Callback for WordPress 'admin_notices' action.
- *
- * Delegate actions to display an error message on the plugin table row if present.
- *
- * @link https://developer.wordpress.org/reference/hooks/admin_notices/
- *
- * @return void
- */
-function delegate_plugin_row_notice() {
- $screen = get_current_screen();
- if ( ! isset( $screen->id ) || 'plugins' !== $screen->id ) {
- return;
- }
-
- $error = get_plugin_api_error();
- if ( ! $error ) {
- return;
- }
-
- $plugin_basename = plugin_basename( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE );
-
- remove_action( "after_plugin_row_{$plugin_basename}", 'wp_plugin_update_row' );
- add_action( "after_plugin_row_{$plugin_basename}", __NAMESPACE__ . '\display_plugin_row_notice', 10 );
-}
-
-/**
- * Callback for WordPress 'after_plugin_row_{plugin_basename}' action.
- *
- * Callback added in add_plugin_page_notices().
- *
- * Show a notice in the plugin table row when there is an error present.
- *
- * @return void
- */
-function display_plugin_row_notice() {
- $error = get_plugin_api_error();
-
- ?>
-
-
-
- |
-
- id ) || 'update-core' !== $screen->id ) {
- return;
- }
-
- // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only used to avoid displaying messages when inappropriate.
- if ( ! empty( $_GET['action'] ) && 'do-theme-upgrade' === $_GET['action'] ) {
- return;
- }
-
- $error = get_plugin_api_error();
- if ( ! $error ) {
- return;
- }
-
- ?>
-
-
' . __( 'THIS UPDATE MAY CONTAIN BREAKING CHANGES: This plugin uses Semantic Versioning, and this new version is a major release. Please review the changelog before updating.', 'wp-graphql-content-blocks' );
-}
diff --git a/includes/PluginUpdater/UpdateFunctions.php b/includes/PluginUpdater/UpdateFunctions.php
deleted file mode 100644
index 3f554182..00000000
--- a/includes/PluginUpdater/UpdateFunctions.php
+++ /dev/null
@@ -1,154 +0,0 @@
-requires_at_least, '>=' );
-
- $api = new stdClass();
- $api->author = 'WP Engine';
- $api->homepage = 'https://wpengine.com';
- $api->name = $product_info->name;
- $api->requires = isset( $product_info->requires_at_least ) ? $product_info->requires_at_least : $current_plugin_data['RequiresWP'];
- $api->sections['changelog'] = isset( $product_info->sections->changelog ) ? $product_info->sections->changelog : '1.0
';
- $api->slug = 'wp-graphql-content-blocks';
-
- // Only pass along the update info if the requirements are met and there's actually a newer version.
- if ( $meets_wp_req && version_compare( $current_plugin_data['Version'], $product_info->version, '<' ) ) {
- $api->version = $product_info->version;
- $api->download_link = $product_info->download_link;
- }
-
- return $api;
-}
-
-/**
- * Fetches and returns the plugin info api error.
- *
- * @return mixed|false The plugin api error or false.
- */
-function get_plugin_api_error() {
- return get_option( 'wpgraphql_content_blocks_product_info_api_error', false );
-}
-
-/**
- * Retrieve remote plugin information from the custom endpoint.
- *
- * @return \stdClass
- */
-function get_remote_plugin_info() {
- $current_plugin_data = \get_plugin_data( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE );
- $response = get_transient( 'wpgraphql_content_blocks_product_info' );
-
- if ( false === $response ) {
- $request_args = [
- 'timeout' => ( ( defined( 'DOING_CRON' ) && DOING_CRON ) ? 30 : 3 ),
- 'user-agent' => 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ),
- 'body' => [
- 'version' => $current_plugin_data['Version'],
- ],
- ];
-
- $response = request_plugin_updates( $request_args );
- if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
- if ( is_wp_error( $response ) ) {
- update_option( 'wpgraphql_content_blocks_product_info_api_error', $response->get_error_code(), false );
- } else {
- $response_body = json_decode( wp_remote_retrieve_body( $response ), false );
- $error_code = ! empty( $response_body->error_code ) ? $response_body->error_code : 'unknown';
- update_option( 'wpgraphql_content_blocks_product_info_api_error', $error_code, false );
- }
-
- $response = new stdClass();
-
- set_transient( 'wpgraphql_content_blocks_product_info', $response, MINUTE_IN_SECONDS * 5 );
-
- return $response;
- }
-
- delete_option( 'wpgraphql_content_blocks_product_info_api_error' );
-
- $response = json_decode(
- wp_remote_retrieve_body( $response )
- );
-
- if ( ! property_exists( $response, 'icons' ) || empty( $response->icons['default'] ) ) {
- $plugin_url = plugin_dir_url( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE );
-
- $response->icons['default'] = $plugin_url . 'includes/updates/images/wpe-logo-stacked-inverse.svg';
- }
-
- set_transient( 'wpgraphql_content_blocks_product_info', $response, HOUR_IN_SECONDS * 12 );
- }
-
- return $response;
-}
-
-/**
- * Get the remote plugin api error message.
- *
- * @param string $reason The reason/error code received the API.
- *
- * @return string The error message.
- */
-function get_api_error_text( string $reason ): string {
- switch ( $reason ) {
- case 'key-unknown':
- return __( 'The product you requested information for is unknown. Please contact support.', 'wp-graphql-content-blocks' );
-
- default:
- return sprintf(
- /* translators: %1$s: Link to GitHub issues. %2$s: The text that is linked. */
- __(
- 'WPGraphQL Content Blocks encountered an unknown error connecting to the update service. This issue could be temporary. Please %2$s if this error persists.',
- 'wp-graphql-content-blocks'
- ),
- 'https://github.com/wpengine/wp-graphql-content-blocks/issues',
- esc_html__( 'contact support', 'wp-graphql-content-blocks' )
- );
- }
-}
-
-/**
- * Retrieve plugin update information via http GET request.
- *
- * @param array $args Array of request args.
- *
- * @return array|\WP_Error A response as an array or WP_Error.
- * @uses wp_remote_get()
- * @link https://developer.wordpress.org/reference/functions/wp_remote_get/
- */
-function request_plugin_updates( array $args = [] ) {
- return wp_remote_get(
- 'https://wp-product-info.wpesvc.net/v1/plugins/wpgraphql-content-blocks',
- $args
- );
-}
diff --git a/includes/Updates/CheckForUpgrades.php b/includes/Updates/CheckForUpgrades.php
new file mode 100644
index 00000000..3b501824
--- /dev/null
+++ b/includes/Updates/CheckForUpgrades.php
@@ -0,0 +1,19 @@
+ 'wp-graphql-content-blocks',
+ 'plugin_basename' => WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_PATH,
+ );
+
+ require_once __DIR__ . '/PluginUpdater.php';
+ new PluginUpdater( $properties );
+ }
+
+ add_action( 'admin_init', __NAMESPACE__ . '\wp_graphql_content_blocks_check_for_upgrades' );
+}
\ No newline at end of file
diff --git a/includes/Updates/PluginUpdater.php b/includes/Updates/PluginUpdater.php
new file mode 100644
index 00000000..e3f013ba
--- /dev/null
+++ b/includes/Updates/PluginUpdater.php
@@ -0,0 +1,247 @@
+api_url = 'https://wpe-plugin-updates.wpengine.com/';
+
+ $this->cache_time = time() + HOUR_IN_SECONDS * 5;
+
+ $this->properties = $this->get_full_plugin_properties( $properties, $this->api_url );
+
+ if ( ! $this->properties ) {
+ return;
+ }
+
+ $this->register();
+ }
+
+ /**
+ * Get the full plugin properties, including the directory name, version, basename, and add a transient name.
+ *
+ * @param array $properties These properties are passed in when instantiating to identify the plugin and it's update location.
+ * @param string $api_url The URL where the api is located.
+ * @return array|null
+ */
+ public function get_full_plugin_properties( $properties, $api_url ) {
+ $plugins = \get_plugins();
+
+ // Scan through all plugins installed and find the one which matches this one in question.
+ foreach ( $plugins as $plugin_basename => $plugin_data ) {
+ // Match using the passed-in plugin's basename.
+ if ( $plugin_basename === $properties['plugin_basename'] ) {
+ // Add the values we need to the properties.
+ $properties['plugin_dirname'] = dirname( $plugin_basename );
+ $properties['plugin_version'] = $plugin_data['Version'];
+ $properties['plugin_update_transient_name'] = 'wpesu-plugin-' . sanitize_title( $properties['plugin_dirname'] );
+ $properties['plugin_update_transient_exp_name'] = 'wpesu-plugin-' . sanitize_title( $properties['plugin_dirname'] ) . '-expiry';
+ $properties['plugin_manifest_url'] = trailingslashit( $api_url ) . trailingslashit( $properties['plugin_slug'] ) . 'info.json';
+
+ return $properties;
+ }
+ }
+
+ // No matching plugin was found installed.
+ return null;
+ }
+
+ /**
+ * Register hooks.
+ *
+ * @return void
+ */
+ public function register() {
+ add_filter( 'plugins_api', array( $this, 'filter_plugin_update_info' ), 20, 3 );
+ add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'filter_plugin_update_transient' ) );
+ }
+
+ /**
+ * Filter the plugin update transient to take over update notifications.
+ *
+ * @param ?object $transient_value The value of the `site_transient_update_plugins` transient.
+ *
+ * @handles site_transient_update_plugins
+ * @return object
+ */
+ public function filter_plugin_update_transient( $transient_value ) {
+ // No update object exists. Return early.
+ if ( empty( $transient_value ) ) {
+ return $transient_value;
+ }
+
+ $result = $this->fetch_plugin_info();
+
+ if ( false === $result ) {
+ return $transient_value;
+ }
+
+ $res = $this->parse_plugin_info( $result );
+
+ if ( version_compare( $this->properties['plugin_version'], $result->version, '<' ) ) {
+ $transient_value->response[ $res->plugin ] = $res;
+ $transient_value->checked[ $res->plugin ] = $result->version;
+ } else {
+ $transient_value->no_update[ $res->plugin ] = $res;
+ }
+
+ return $transient_value;
+ }
+
+ /**
+ * Filters the plugin update information.
+ *
+ * @param object $res The response to be modified for the plugin in question.
+ * @param string $action The action in question.
+ * @param object $args The arguments for the plugin in question.
+ *
+ * @handles plugins_api
+ * @return object
+ */
+ public function filter_plugin_update_info( $res, $action, $args ) {
+ // Do nothing if this is not about getting plugin information.
+ if ( 'plugin_information' !== $action ) {
+ return $res;
+ }
+
+ // Do nothing if it is not our plugin.
+ if ( $this->properties['plugin_dirname'] !== $args->slug ) {
+ return $res;
+ }
+
+
+ $result = $this->fetch_plugin_info();
+
+ // Do nothing if we don't get the correct response from the server.
+ if ( false === $result ) {
+ return $res;
+ }
+
+ return $this->parse_plugin_info( $result );
+ }
+
+ /**
+ * Fetches the plugin update object from the WP Product Info API.
+ *
+ * @return object|false
+ */
+ private function fetch_plugin_info() {
+ // Fetch cache first.
+ $expiry = get_option( $this->properties['plugin_update_transient_exp_name'], 0 );
+ $response = get_option( $this->properties['plugin_update_transient_name'] );
+
+ if ( empty( $expiry ) || time() > $expiry || empty( $response ) ) {
+ $response = wp_remote_get(
+ $this->properties['plugin_manifest_url'],
+ array(
+ 'timeout' => 10,
+ 'headers' => array(
+ 'Accept' => 'application/json',
+ ),
+ )
+ );
+
+ if (
+ is_wp_error( $response ) ||
+ 200 !== wp_remote_retrieve_response_code( $response ) ||
+ empty( wp_remote_retrieve_body( $response ) )
+ ) {
+ return false;
+ }
+
+ $response = wp_remote_retrieve_body( $response );
+
+ // Cache the response.
+ update_option( $this->properties['plugin_update_transient_exp_name'], $this->cache_time, false );
+ update_option( $this->properties['plugin_update_transient_name'], $response, false );
+ }
+
+ $decoded_response = json_decode( $response );
+
+ if ( json_last_error() !== JSON_ERROR_NONE ) {
+ return false;
+ }
+
+ return $decoded_response;
+ }
+
+ /**
+ * Parses the product info response into an object that WordPress would be able to understand.
+ *
+ * @param object $response The response object.
+ *
+ * @return stdClass
+ */
+ private function parse_plugin_info( $response ) {
+
+ global $wp_version;
+
+ $res = new stdClass();
+ $res->name = $response->name;
+ $res->slug = $response->slug;
+ $res->version = $response->version;
+ $res->requires = $response->requires;
+ $res->download_link = $response->download_link;
+ $res->trunk = $response->download_link;
+ $res->new_version = $response->version;
+ $res->plugin = $this->properties['plugin_basename'];
+ $res->package = $response->download_link;
+
+ // Plugin information modal and core update table use a strict version comparison, which is weird.
+ // If we're genuinely not compatible with the point release, use our WP tested up to version.
+ // otherwise use exact same version as WP to avoid false positive.
+ $res->tested = 1 === version_compare( substr( $wp_version, 0, 3 ), $response->tested )
+ ? $response->tested
+ : $wp_version;
+
+ $res->sections = array(
+ 'description' => $response->sections->description,
+ 'changelog' => $response->sections->changelog,
+ );
+
+ return $res;
+ }
+}
\ No newline at end of file
diff --git a/includes/WPGraphQLContentBlocks.php b/includes/WPGraphQLContentBlocks.php
index 554a551f..b34c4578 100644
--- a/includes/WPGraphQLContentBlocks.php
+++ b/includes/WPGraphQLContentBlocks.php
@@ -98,8 +98,9 @@ static function () {
}
// Include the updater functions.
- require_once WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR . '/includes/PluginUpdater/UpdateFunctions.php';
- require_once WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR . '/includes/PluginUpdater/UpdateCallbacks.php';
+ if (file_exists(WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR . '/includes/Updates/CheckForUpgrades.php')) {
+ require_once WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_DIR . '/includes/Updates/CheckForUpgrades.php';
+ }
// Bail if the Enforce SemVer class doesn't exist.
if ( ! class_exists( 'EnforceSemVer\EnforceSemVer' ) ) {
diff --git a/wp-graphql-content-blocks.php b/wp-graphql-content-blocks.php
index 0f2c1d02..d4f816cf 100644
--- a/wp-graphql-content-blocks.php
+++ b/wp-graphql-content-blocks.php
@@ -42,9 +42,18 @@ function wpgraphql_content_blocks_constants(): void {
if ( ! defined( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_PATH' ) ) {
define( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_PATH', plugin_basename( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_FILE ) );
}
+
if ( ! defined( 'WPGRAPHQL_CONTENT_BLOCKS_VERSION' ) ) {
define( 'WPGRAPHQL_CONTENT_BLOCKS_VERSION', '4.5.0' );
}
+
+ if ( ! defined( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_URL' ) ) {
+ define( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
+ }
+
+ if ( ! defined( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_PATH' ) ) {
+ define( 'WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_PATH', plugin_basename( WPGRAPHQL_CONTENT_BLOCKS_PLUGIN_URL ) );
+ }
}
}