diff --git a/backport-changelog/7.0/11701.md b/backport-changelog/7.0/11701.md new file mode 100644 index 00000000000000..48049f2db1eb61 --- /dev/null +++ b/backport-changelog/7.0/11701.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/11701 + +* https://github.com/WordPress/gutenberg/pull/77897 diff --git a/lib/compat/wordpress-7.0/class-wp-connector-registry.php b/lib/compat/wordpress-7.0/class-wp-connector-registry.php index e6fbd2d5842c5f..bb4c0a8d619983 100644 --- a/lib/compat/wordpress-7.0/class-wp-connector-registry.php +++ b/lib/compat/wordpress-7.0/class-wp-connector-registry.php @@ -27,9 +27,9 @@ * constant_name?: non-empty-string, * env_var_name?: non-empty-string * }, - * plugin?: array{ - * file: non-empty-string, - * is_active?: callable(): bool + * plugin: array{ + * file?: non-empty-string, + * is_active: callable(): bool * } * } */ @@ -98,10 +98,12 @@ final class WP_Connector_Registry { * @type array $plugin { * Optional. Plugin data for install/activate UI. * - * @type string $file The plugin's main file path relative to the plugins - * directory (e.g. 'akismet/akismet.php' or 'hello.php'). + * @type string $file Optional. The plugin's main file path relative to the + * plugins directory (e.g. 'my-plugin/my-plugin.php' or + * 'hello.php'). * @type callable $is_active Optional callback to determine whether the plugin * is active. Receives no arguments and must return bool. + * Defaults to `__return_true`. * } * } * @return array|null The registered connector data on success, null on failure. @@ -234,8 +236,12 @@ public function register( string $id, array $args ): ?array { } } - if ( ! empty( $args['plugin'] ) && is_array( $args['plugin'] ) && ! empty( $args['plugin']['file'] ) ) { - $connector['plugin'] = array( 'file' => $args['plugin']['file'] ); + $connector['plugin'] = array(); + + if ( ! empty( $args['plugin'] ) && is_array( $args['plugin'] ) ) { + if ( ! empty( $args['plugin']['file'] ) ) { + $connector['plugin']['file'] = $args['plugin']['file']; + } if ( isset( $args['plugin']['is_active'] ) ) { if ( ! is_callable( $args['plugin']['is_active'] ) ) { @@ -252,6 +258,10 @@ public function register( string $id, array $args ): ?array { } } + if ( ! isset( $connector['plugin']['is_active'] ) ) { + $connector['plugin']['is_active'] = '__return_true'; + } + $this->registered_connectors[ $id ] = $connector; return $connector; } diff --git a/lib/experimental/connectors/default-connectors.php b/lib/experimental/connectors/default-connectors.php index 2d08f162738004..5a2b48a6f3d570 100644 --- a/lib/experimental/connectors/default-connectors.php +++ b/lib/experimental/connectors/default-connectors.php @@ -31,7 +31,10 @@ function _gutenberg_connectors_init(): void { 'description' => __( 'Protect your site from spam.', 'gutenberg' ), 'type' => 'spam_filtering', 'plugin' => array( - 'file' => 'akismet/akismet.php', + 'file' => 'akismet/akismet.php', + 'is_active' => static function (): bool { + return defined( 'AKISMET_VERSION' ); + }, ), 'authentication' => array( 'method' => 'api_key', @@ -201,6 +204,17 @@ function _gutenberg_register_default_ai_providers( WP_Connector_Registry $regist } } } + + if ( ! isset( $args['plugin']['is_active'] ) ) { + $args['plugin']['is_active'] = static function () use ( $ai_registry, $id ): bool { + try { + return $ai_registry->hasProvider( $id ); + } catch ( Exception $e ) { + return false; + } + }; + } + $registry->register( $id, $args ); } } @@ -485,7 +499,7 @@ function _gutenberg_get_connector_script_module_data( array $data ): array { $registry = \WordPress\AiClient\AiClient::defaultRegistry(); - if ( ! function_exists( 'is_plugin_active' ) ) { + if ( ! function_exists( 'validate_plugin' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } @@ -525,22 +539,8 @@ function _gutenberg_get_connector_script_module_data( array $data ): array { if ( ! empty( $connector_data['plugin']['file'] ) ) { $file = $connector_data['plugin']['file']; - $is_installed = false; - $is_activated = false; - - if ( ! empty( $connector_data['plugin']['is_active'] ) && is_callable( $connector_data['plugin']['is_active'] ) ) { - $is_activated = (bool) call_user_func( $connector_data['plugin']['is_active'] ); - } - - if ( ! $is_activated ) { - $is_activated = is_plugin_active( $file ); - } - - if ( $is_activated ) { - $is_installed = true; - } else { - $is_installed = file_exists( WP_PLUGIN_DIR . '/' . $file ); - } + $is_activated = (bool) call_user_func( $connector_data['plugin']['is_active'] ); + $is_installed = $is_activated || 0 === validate_plugin( $file ); $connector_out['plugin'] = array( 'file' => $file, diff --git a/test/e2e/specs/admin/connectors.spec.js b/test/e2e/specs/admin/connectors.spec.js index 404b6a387054ea..0e891d67a10cbe 100644 --- a/test/e2e/specs/admin/connectors.spec.js +++ b/test/e2e/specs/admin/connectors.spec.js @@ -53,7 +53,7 @@ test.describe( 'Connectors', () => { ); } ); - test( 'should display default providers with setup buttons', async ( { + test( 'should display default providers with install buttons', async ( { page, admin, } ) => { @@ -66,7 +66,7 @@ test.describe( 'Connectors', () => { } ); await expect( pageTitle ).toBeVisible(); - // Verify each connector card shows name as heading, description, and Set up button. + // Verify each connector card shows name as heading, description, and Install button. for ( const { slug, name, description } of CONNECTORS ) { const card = page.locator( `.connector-item--${ slug }` ); await expect( card ).toBeVisible(); @@ -86,9 +86,9 @@ test.describe( 'Connectors', () => { headingId ); - const button = card.getByRole( 'button', { name: 'Set up' } ); + const button = card.getByRole( 'button', { name: 'Install' } ); await expect( button ).toBeVisible(); - // Set up button should not have aria-expanded until expanded. + // Install button should not have aria-expanded until expanded. await expect( button ).not.toHaveAttribute( 'aria-expanded' ); }