diff --git a/src/wp-admin/options-connectors.php b/src/wp-admin/options-connectors.php index eacb9bdb5f7aa..60e29d158d38a 100644 --- a/src/wp-admin/options-connectors.php +++ b/src/wp-admin/options-connectors.php @@ -74,9 +74,15 @@ function _wp_connectors_preload_paths( array $preload_paths ): array { } add_filter( 'wp_options_connectors_wp_admin_preload_paths', '_wp_connectors_preload_paths' ); +// Used to install connector plugins when filesystem credentials are required. +wp_enqueue_script( 'updates' ); + require_once ABSPATH . 'wp-admin/admin-header.php'; // Render the Connectors page. wp_options_connectors_wp_admin_render_page(); +wp_print_request_filesystem_credentials_modal(); +wp_print_admin_notice_templates(); + require_once ABSPATH . 'wp-admin/admin-footer.php'; diff --git a/src/wp-includes/connectors.php b/src/wp-includes/connectors.php index 88f6a5b964f99..1bf43009bb3a7 100644 --- a/src/wp-includes/connectors.php +++ b/src/wp-includes/connectors.php @@ -900,6 +900,7 @@ function _wp_connectors_pass_default_keys_to_ai_client(): void { * Exposes connector settings to the connectors-wp-admin script module. * * @since 7.0.0 + * @since 7.2.0 Added the `filesystemCredentialsRequired` flag. * @access private * * @param array $data Existing script module data. @@ -912,6 +913,10 @@ function _wp_connectors_get_connector_script_module_data( array $data ): array { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } + if ( ! function_exists( 'request_filesystem_credentials' ) ) { + require_once ABSPATH . 'wp-admin/includes/file.php'; + } + $connectors = array(); foreach ( wp_get_connectors() as $connector_id => $connector_data ) { $auth = $connector_data['authentication']; @@ -966,6 +971,22 @@ function _wp_connectors_get_connector_script_module_data( array $data ): array { ksort( $connectors ); $data['connectors'] = $connectors; $data['isFileModDisabled'] = ! wp_is_file_mod_allowed( 'install_plugins' ); + + /* + * The REST API plugins endpoint cannot install plugins when the filesystem + * method requires credentials that have not been stored. In that case, the + * client installs through `wp.updates.installPlugin()` instead, which prompts + * for the credentials with the "Connection Information" modal. + */ + $data['filesystemCredentialsRequired'] = false; + if ( 'direct' !== get_filesystem_method() ) { + ob_start(); + $filesystem_credentials_are_stored = request_filesystem_credentials( self_admin_url() ); + ob_end_clean(); + + $data['filesystemCredentialsRequired'] = ! $filesystem_credentials_are_stored; + } + return $data; } add_filter( 'script_module_data_options-connectors-wp-admin', '_wp_connectors_get_connector_script_module_data' ); diff --git a/tests/phpunit/tests/connectors/wpConnectorsGetConnectorScriptModuleData.php b/tests/phpunit/tests/connectors/wpConnectorsGetConnectorScriptModuleData.php index b9b5014affdd1..7512bcf502227 100644 --- a/tests/phpunit/tests/connectors/wpConnectorsGetConnectorScriptModuleData.php +++ b/tests/phpunit/tests/connectors/wpConnectorsGetConnectorScriptModuleData.php @@ -209,4 +209,53 @@ public function test_environment_variable_password_may_contain_colons(): void { $this->assertSame( 'env', $auth['keySource'] ); $this->assertTrue( $auth['isConnected'] ); } + + /** + * @ticket 65223 + */ + public function test_filesystem_credentials_not_required_for_direct_filesystem_method(): void { + add_filter( + 'filesystem_method', + static function () { + return 'direct'; + } + ); + + $data = _wp_connectors_get_connector_script_module_data( array() ); + + $this->assertFalse( $data['filesystemCredentialsRequired'] ); + } + + /** + * @ticket 65223 + */ + public function test_filesystem_credentials_required_when_credentials_are_not_stored(): void { + add_filter( + 'filesystem_method', + static function () { + return 'ftpext'; + } + ); + + $data = _wp_connectors_get_connector_script_module_data( array() ); + + $this->assertTrue( $data['filesystemCredentialsRequired'] ); + } + + /** + * @ticket 65223 + */ + public function test_filesystem_credentials_not_required_when_credentials_are_stored(): void { + add_filter( + 'filesystem_method', + static function () { + return 'ftpext'; + } + ); + add_filter( 'request_filesystem_credentials', '__return_true' ); + + $data = _wp_connectors_get_connector_script_module_data( array() ); + + $this->assertFalse( $data['filesystemCredentialsRequired'] ); + } }