Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions backport-changelog/7.0/11701.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
https://github.com/WordPress/wordpress-develop/pull/11701

* https://github.com/WordPress/gutenberg/pull/77897
24 changes: 17 additions & 7 deletions lib/compat/wordpress-7.0/class-wp-connector-registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
* }
Comment on lines +30 to 33

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

* }
*/
Expand Down Expand Up @@ -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.
Comment thread
westonruter marked this conversation as resolved.
* Defaults to `__return_true`.
* }
* }
* @return array|null The registered connector data on success, null on failure.
Expand Down Expand Up @@ -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'] ) ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible here that $args['plugin']['file'] is not a string. Not likely, but just wanted to point that this is not validated here. If that validation is added here, it should be added as well to the core PR.

$connector['plugin']['file'] = $args['plugin']['file'];
}

if ( isset( $args['plugin']['is_active'] ) ) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we aligned with core and set $connector['plugin']['is_active'] == '__return_true', if a is_active was not passed?

@westonruter westonruter May 5, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that in the phpdoc for \WP_Connector_Registry::register() in core:

	 *         @type callable $is_active Optional callback to determine whether the plugin
	 *                                   is active. Receives no arguments and must return bool.
	 *                                   Defaults to `__return_true`.

and in the method:

		if ( ! isset( $connector['plugin']['is_active'] ) ) {
			$connector['plugin']['is_active'] = '__return_true';
		}

So it does seem to make sense to update this to match what is in core.

This aligns with what was done in WordPress/wordpress-develop@b3b40be.

This would undo some things in the companion core PR: WordPress/wordpress-develop#11701

if ( ! is_callable( $args['plugin']['is_active'] ) ) {
Expand All @@ -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;
}
Expand Down
36 changes: 18 additions & 18 deletions lib/experimental/connectors/default-connectors.php
Original file line number Diff line number Diff line change
Expand Up @@ -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' );
},
Comment thread
t-hamano marked this conversation as resolved.
),
'authentication' => array(
'method' => 'api_key',
Expand Down Expand Up @@ -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 );
}
}
Expand Down Expand Up @@ -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';
}

Expand Down Expand Up @@ -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,
Expand Down
8 changes: 4 additions & 4 deletions test/e2e/specs/admin/connectors.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
} ) => {
Expand All @@ -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();
Expand All @@ -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' );
}

Expand Down
Loading