Skip to content

Commit b3b40be

Browse files
Connectors: Add is_active callback support to plugin registration.
Adds an optional `is_active` callable to the `plugin` definition accepted by `WP_Connector_Registry::register()`. The callback receives no arguments, must return a boolean, and is used by the Connectors screen to decide whether a connector's backing plugin is currently active. When omitted, it defaults to `__return_true`; when provided but not callable, registration fails with a `_doing_it_wrong()` notice. Developed in: #11565 Props iamadisingh, jorgefilipecosta, mukesh27, gziolo. Fixes #65020. git-svn-id: https://develop.svn.wordpress.org/trunk@62288 602fd350-edb4-49c9-b593-d223f7449a82
1 parent ddb5edd commit b3b40be

3 files changed

Lines changed: 98 additions & 14 deletions

File tree

src/wp-includes/class-wp-connector-registry.php

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
* env_var_name?: non-empty-string
4141
* },
4242
* plugin?: array{
43-
* file: non-empty-string
43+
* file: non-empty-string,
44+
* is_active?: callable(): bool
4445
* }
4546
* }
4647
*/
@@ -109,8 +110,12 @@ final class WP_Connector_Registry {
109110
* @type array $plugin {
110111
* Optional. Plugin data for install/activate UI.
111112
*
112-
* @type string $file The plugin's main file path relative to the plugins
113-
* directory (e.g. 'my-plugin/my-plugin.php' or 'hello.php').
113+
* @type string $file Optional. The plugin's main file path relative to the
114+
* plugins directory (e.g. 'my-plugin/my-plugin.php' or
115+
* 'hello.php').
116+
* @type callable $is_active Optional callback to determine whether the plugin
117+
* is active. Receives no arguments and must return bool.
118+
* Defaults to `__return_true`.
114119
* }
115120
* }
116121
* @return array|null The registered connector data on success, null on failure.
@@ -243,8 +248,30 @@ public function register( string $id, array $args ): ?array {
243248
}
244249
}
245250

246-
if ( ! empty( $args['plugin'] ) && is_array( $args['plugin'] ) && ! empty( $args['plugin']['file'] ) ) {
247-
$connector['plugin'] = array( 'file' => $args['plugin']['file'] );
251+
$connector['plugin'] = array();
252+
253+
if ( ! empty( $args['plugin'] ) && is_array( $args['plugin'] ) ) {
254+
if ( ! empty( $args['plugin']['file'] ) ) {
255+
$connector['plugin']['file'] = $args['plugin']['file'];
256+
}
257+
258+
if ( isset( $args['plugin']['is_active'] ) ) {
259+
if ( ! is_callable( $args['plugin']['is_active'] ) ) {
260+
_doing_it_wrong(
261+
__METHOD__,
262+
/* translators: %s: Connector ID. */
263+
sprintf( __( 'Connector "%s" plugin is_active must be callable.' ), esc_html( $id ) ),
264+
'7.0.0'
265+
);
266+
return null;
267+
}
268+
269+
$connector['plugin']['is_active'] = $args['plugin']['is_active'];
270+
}
271+
}
272+
273+
if ( ! isset( $connector['plugin']['is_active'] ) ) {
274+
$connector['plugin']['is_active'] = '__return_true';
248275
}
249276

250277
$this->registered_connectors[ $id ] = $connector;

src/wp-includes/connectors.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,17 @@ function _wp_connectors_register_default_ai_providers( WP_Connector_Registry $re
367367
}
368368
}
369369
}
370+
371+
if ( ! isset( $args['plugin']['is_active'] ) ) {
372+
$args['plugin']['is_active'] = static function () use ( $ai_registry, $id ): bool {
373+
try {
374+
return $ai_registry->hasProvider( $id );
375+
} catch ( Exception $e ) {
376+
return false;
377+
}
378+
};
379+
}
380+
370381
$registry->register( $id, $args );
371382
}
372383
}
@@ -638,10 +649,6 @@ function _wp_connectors_pass_default_keys_to_ai_client(): void {
638649
function _wp_connectors_get_connector_script_module_data( array $data ): array {
639650
$registry = AiClient::defaultRegistry();
640651

641-
if ( ! function_exists( 'is_plugin_active' ) ) {
642-
require_once ABSPATH . 'wp-admin/includes/plugin.php';
643-
}
644-
645652
$connectors = array();
646653
foreach ( wp_get_connectors() as $connector_id => $connector_data ) {
647654
$auth = $connector_data['authentication'];
@@ -674,8 +681,8 @@ function _wp_connectors_get_connector_script_module_data( array $data ): array {
674681

675682
if ( ! empty( $connector_data['plugin']['file'] ) ) {
676683
$file = $connector_data['plugin']['file'];
677-
$is_installed = file_exists( wp_normalize_path( WP_PLUGIN_DIR . '/' . $file ) );
678-
$is_activated = $is_installed && is_plugin_active( $file );
684+
$is_activated = (bool) call_user_func( $connector_data['plugin']['is_active'] );
685+
$is_installed = $is_activated || file_exists( wp_normalize_path( WP_PLUGIN_DIR . '/' . $file ) );
679686

680687
$connector_out['plugin'] = array(
681688
'file' => $file,

tests/phpunit/tests/connectors/wpConnectorRegistry.php

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -299,16 +299,66 @@ public function test_register_includes_plugin_data() {
299299
$result = $this->registry->register( 'with-plugin', $args );
300300

301301
$this->assertArrayHasKey( 'plugin', $result );
302-
$this->assertSame( array( 'file' => 'my-plugin/my-plugin.php' ), $result['plugin'] );
302+
$this->assertSame( 'my-plugin/my-plugin.php', $result['plugin']['file'] );
303+
}
304+
305+
/**
306+
* @ticket 65020
307+
*/
308+
public function test_register_stores_plugin_is_active_callback() {
309+
$args = self::$default_args;
310+
$args['plugin'] = array(
311+
'file' => 'my-plugin/my-plugin.php',
312+
'is_active' => '__return_true',
313+
);
314+
315+
$result = $this->registry->register( 'with-callback', $args );
316+
317+
$this->assertIsArray( $result );
318+
$this->assertArrayHasKey( 'is_active', $result['plugin'] );
319+
$this->assertIsCallable( $result['plugin']['is_active'] );
320+
}
321+
322+
/**
323+
* @ticket 65020
324+
*/
325+
public function test_register_rejects_non_callable_plugin_is_active() {
326+
$this->setExpectedIncorrectUsage( 'WP_Connector_Registry::register' );
327+
328+
$args = self::$default_args;
329+
$args['plugin'] = array(
330+
'file' => 'my-plugin/my-plugin.php',
331+
'is_active' => 'not_a_real_function_name',
332+
);
333+
334+
$result = $this->registry->register( 'bad-callback', $args );
335+
336+
$this->assertNull( $result );
337+
}
338+
339+
/**
340+
* @ticket 65020
341+
*/
342+
public function test_register_defaults_plugin_is_active_to_return_true() {
343+
$args = self::$default_args;
344+
$args['plugin'] = array( 'file' => 'my-plugin/my-plugin.php' );
345+
346+
$result = $this->registry->register( 'default-callback', $args );
347+
348+
$this->assertIsArray( $result );
349+
$this->assertArrayHasKey( 'is_active', $result['plugin'] );
350+
$this->assertSame( '__return_true', $result['plugin']['is_active'] );
303351
}
304352

305353
/**
306354
* @ticket 64791
307355
*/
308-
public function test_register_omits_plugin_when_not_provided() {
356+
public function test_register_defaults_plugin_when_not_provided() {
309357
$result = $this->registry->register( 'no-plugin', self::$default_args );
310358

311-
$this->assertArrayNotHasKey( 'plugin', $result );
359+
$this->assertArrayHasKey( 'plugin', $result );
360+
$this->assertArrayNotHasKey( 'file', $result['plugin'] );
361+
$this->assertSame( '__return_true', $result['plugin']['is_active'] );
312362
}
313363

314364
/**

0 commit comments

Comments
 (0)