initial
This commit is contained in:
+182
@@ -0,0 +1,182 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.1.34] - 2026-06-29
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.1.33] - 2026-06-25
|
||||
### Changed
|
||||
- Update package dependencies. [#49831]
|
||||
|
||||
## [0.1.32] - 2026-06-22
|
||||
### Changed
|
||||
- Update package dependencies. [#49631] [#49691] [#49757]
|
||||
|
||||
## [0.1.31] - 2026-06-09
|
||||
### Changed
|
||||
- Update package dependencies. [#49273]
|
||||
|
||||
## [0.1.30] - 2026-06-08
|
||||
### Changed
|
||||
- Update dependencies. [#49354]
|
||||
|
||||
## [0.1.29] - 2026-05-25
|
||||
### Changed
|
||||
- Update package dependencies. [#48405]
|
||||
|
||||
## [0.1.28] - 2026-05-19
|
||||
### Changed
|
||||
- Exclude development files from production builds. [#47365]
|
||||
- Update dependencies. [#48778]
|
||||
|
||||
## [0.1.27] - 2026-05-11
|
||||
### Changed
|
||||
- Update dependencies. [#46383]
|
||||
|
||||
## [0.1.26] - 2026-05-04
|
||||
### Changed
|
||||
- Internal: No longer require automattic/jetpack-changelogger as a per-project dev dependency. [#48225]
|
||||
|
||||
## [0.1.25] - 2026-04-20
|
||||
### Changed
|
||||
- Update package dependencies. [#48106]
|
||||
|
||||
## [0.1.24] - 2026-04-13
|
||||
### Changed
|
||||
- Update package dependencies. [#47890]
|
||||
|
||||
## [0.1.23] - 2026-04-06
|
||||
### Changed
|
||||
- Update dependencies. [#46383]
|
||||
|
||||
## [0.1.22] - 2026-03-30
|
||||
### Changed
|
||||
- Update dependencies. [#46383]
|
||||
|
||||
## [0.1.21] - 2026-03-23
|
||||
### Changed
|
||||
- Update package dependencies. [#47684]
|
||||
|
||||
## [0.1.20] - 2026-03-16
|
||||
### Changed
|
||||
- Update dependencies. [#47472]
|
||||
|
||||
## [0.1.19] - 2026-03-09
|
||||
### Changed
|
||||
- Update package dependencies. [#47496]
|
||||
|
||||
## [0.1.18] - 2026-02-26
|
||||
### Changed
|
||||
- Update package dependencies. [#47300]
|
||||
|
||||
## [0.1.17] - 2026-02-23
|
||||
### Changed
|
||||
- Update package dependencies. [#47173]
|
||||
|
||||
## [0.1.16] - 2026-02-16
|
||||
### Changed
|
||||
- Update package dependencies. [#47099]
|
||||
|
||||
## [0.1.15] - 2026-02-10
|
||||
### Changed
|
||||
- Update package dependencies. [#47002]
|
||||
|
||||
## [0.1.14] - 2026-02-02
|
||||
### Changed
|
||||
- Update package dependencies. [#46854]
|
||||
|
||||
## [0.1.13] - 2026-01-26
|
||||
### Changed
|
||||
- Update dependencies. [#46383]
|
||||
|
||||
## [0.1.12] - 2026-01-19
|
||||
### Changed
|
||||
- Update package dependencies. [#46552] [#46647]
|
||||
|
||||
## [0.1.11] - 2026-01-12
|
||||
### Changed
|
||||
- Update package dependencies. [#46456]
|
||||
|
||||
## [0.1.10] - 2025-12-22
|
||||
### Changed
|
||||
- Update dependencies. [#46381]
|
||||
|
||||
## [0.1.9] - 2025-12-15
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.1.8] - 2025-12-08
|
||||
### Fixed
|
||||
- Ensure proper flags are used with `json_encode()`. [#46092]
|
||||
|
||||
## [0.1.7] - 2025-12-01
|
||||
### Changed
|
||||
- Update package dependencies. [#46143]
|
||||
|
||||
## [0.1.6] - 2025-11-17
|
||||
### Changed
|
||||
- Update package dependencies. [#45915]
|
||||
|
||||
## [0.1.5] - 2025-11-03
|
||||
### Changed
|
||||
- Update dependencies. [#45664]
|
||||
|
||||
## [0.1.4] - 2025-10-06
|
||||
### Changed
|
||||
- Update package dependencies. [#45334]
|
||||
|
||||
## [0.1.3] - 2025-09-22
|
||||
### Changed
|
||||
- Update dependencies.
|
||||
|
||||
## [0.1.2] - 2025-09-19
|
||||
### Changed
|
||||
- Update package dependencies. [#45173] [#45229]
|
||||
|
||||
## [0.1.1] - 2025-09-08
|
||||
### Changed
|
||||
- Update package dependencies. [#45027]
|
||||
|
||||
## 0.1.0 - 2025-09-01
|
||||
### Added
|
||||
- Initial version. [#44858]
|
||||
|
||||
[0.1.34]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.33...v0.1.34
|
||||
[0.1.33]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.32...v0.1.33
|
||||
[0.1.32]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.31...v0.1.32
|
||||
[0.1.31]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.30...v0.1.31
|
||||
[0.1.30]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.29...v0.1.30
|
||||
[0.1.29]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.28...v0.1.29
|
||||
[0.1.28]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.27...v0.1.28
|
||||
[0.1.27]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.26...v0.1.27
|
||||
[0.1.26]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.25...v0.1.26
|
||||
[0.1.25]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.24...v0.1.25
|
||||
[0.1.24]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.23...v0.1.24
|
||||
[0.1.23]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.22...v0.1.23
|
||||
[0.1.22]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.21...v0.1.22
|
||||
[0.1.21]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.20...v0.1.21
|
||||
[0.1.20]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.19...v0.1.20
|
||||
[0.1.19]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.18...v0.1.19
|
||||
[0.1.18]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.17...v0.1.18
|
||||
[0.1.17]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.16...v0.1.17
|
||||
[0.1.16]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.15...v0.1.16
|
||||
[0.1.15]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.14...v0.1.15
|
||||
[0.1.14]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.13...v0.1.14
|
||||
[0.1.13]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.12...v0.1.13
|
||||
[0.1.12]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.11...v0.1.12
|
||||
[0.1.11]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.10...v0.1.11
|
||||
[0.1.10]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.9...v0.1.10
|
||||
[0.1.9]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.8...v0.1.9
|
||||
[0.1.8]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.7...v0.1.8
|
||||
[0.1.7]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.6...v0.1.7
|
||||
[0.1.6]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.5...v0.1.6
|
||||
[0.1.5]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.4...v0.1.5
|
||||
[0.1.4]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.3...v0.1.4
|
||||
[0.1.3]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.2...v0.1.3
|
||||
[0.1.2]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.1...v0.1.2
|
||||
[0.1.1]: https://github.com/Automattic/jetpack-external-connections/compare/v0.1.0...v0.1.1
|
||||
+1
@@ -0,0 +1 @@
|
||||
<?php return array('dependencies' => array('react-dom', 'react-jsx-runtime', 'wp-dom-ready', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-polyfill'), 'version' => '2a33dbc0026f7152568f');
|
||||
+1
@@ -0,0 +1 @@
|
||||
.jetpack-external-connection-settings{align-items:center;display:flex;gap:4px;min-height:30px}.jetpack-external-connection-settings img{width:20px}
|
||||
+1
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
||||
.jetpack-external-connection-settings{align-items:center;display:flex;gap:4px;min-height:30px}.jetpack-external-connection-settings img{width:20px}
|
||||
+346
@@ -0,0 +1,346 @@
|
||||
<?php
|
||||
/**
|
||||
* Management of external connections.
|
||||
*
|
||||
* @package automattic/jetpack-external-connections
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack;
|
||||
|
||||
use Automattic\Jetpack\Connection\Client;
|
||||
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
|
||||
use Automattic\Jetpack\Status\Host;
|
||||
|
||||
/**
|
||||
* Main class.
|
||||
*/
|
||||
class External_Connections {
|
||||
|
||||
const PACKAGE_VERSION = '0.1.34';
|
||||
const BASE_FILE = __FILE__;
|
||||
|
||||
/**
|
||||
* List of services whose connections are managed in settings pages.
|
||||
*
|
||||
* Each item has a key with the slug of the settings page, and a value with an array of services.
|
||||
*
|
||||
* Each service has the following keys:
|
||||
* - service: The service identifier.
|
||||
* - title: The title of the service.
|
||||
* - signup_link: The URL to the service's signup page.
|
||||
* - description: The description of the service.
|
||||
* - support_link: An array with the following keys:
|
||||
* - jetpack: The URL handler registered in jetpack.com/redirect/.
|
||||
* - wpcom: The URL of the support page for the service on WordPress.com.
|
||||
* - script: An optional script handle to enqueue.
|
||||
*
|
||||
* @example
|
||||
* ```php
|
||||
* self::$services = array(
|
||||
* 'media' => array(
|
||||
* array(
|
||||
* 'service' => 'facebook',
|
||||
* 'title' => 'Facebook',
|
||||
* 'signup_link' => 'https://facebook.com/signup?ref=jetpack',
|
||||
* 'description' => 'Connect your site to your Facebook account',
|
||||
* 'support_link' => array(
|
||||
* 'jetpack' => 'facebook-connection',
|
||||
* 'wpcom' => 'https://wordpress.com/support/facebook/',
|
||||
* ),
|
||||
* ),
|
||||
* ),
|
||||
* );
|
||||
* ```
|
||||
* @var array
|
||||
*/
|
||||
private static $services = array();
|
||||
|
||||
/**
|
||||
* Gets the connect URL for a given service.
|
||||
*
|
||||
* @param string $service The service identifier.
|
||||
* @return string|null The connect URL, or `null` if the service is not supported.
|
||||
*/
|
||||
public static function get_connect_url( $service ) {
|
||||
if ( ( new Host() )->is_wpcom_simple() ) {
|
||||
require_lib( 'external-connections' );
|
||||
$connections = \WPCOM_External_Connections::init();
|
||||
$service = $connections->get_external_service_item( $service );
|
||||
return $service ? $service['connect_URL'] : null;
|
||||
}
|
||||
|
||||
$site_id = Connection_Manager::get_site_id();
|
||||
if ( is_wp_error( $site_id ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$path = sprintf( '/sites/%d/external-services', $site_id );
|
||||
$response = Client::wpcom_json_api_request_as_user( $path );
|
||||
if ( is_wp_error( $response ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$body = json_decode( wp_remote_retrieve_body( $response ) );
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
|
||||
return $body->services->$service->connect_URL ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a connection of the provided service.
|
||||
*
|
||||
* @param string $service The service identifier.
|
||||
* @return array|null The connection details, or `null` if no matching connection is found.
|
||||
*/
|
||||
public static function get_connection( $service ) {
|
||||
if ( ( new Host() )->is_wpcom_simple() ) {
|
||||
require_lib( 'external-media-service/external-media-list' );
|
||||
require_lib( 'external-connections' );
|
||||
|
||||
$connections = \WPCOM_External_Connections::init();
|
||||
$token = \ExternalMediaService::get_service_token( $service, get_current_user_id() );
|
||||
|
||||
if ( ! empty( $token->unique_id ) ) {
|
||||
// @phan-suppress-next-line PhanTypeMismatchArgument -- $token->unique_id is an int.
|
||||
return $connections->get_keyring_connection_item( $token->unique_id );
|
||||
}
|
||||
} else {
|
||||
$response = Client::wpcom_json_api_request_as_user( '/me/connections' );
|
||||
if ( is_wp_error( $response ) ) {
|
||||
return null;
|
||||
}
|
||||
$body = json_decode( wp_remote_retrieve_body( $response ) );
|
||||
if ( isset( $body->connections ) && is_array( $body->connections ) ) {
|
||||
foreach ( $body->connections as $connection ) {
|
||||
if ( $service === $connection->service ) {
|
||||
return (array) $connection;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a connection for the provided service.
|
||||
*
|
||||
* @param string $service The service identifier.
|
||||
* @return boolean Whether the connection was deleted.
|
||||
*/
|
||||
public static function delete_connection( $service ) {
|
||||
$connection = self::get_connection( $service );
|
||||
if ( empty( $connection ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ( new Host() )->is_wpcom_simple() ) {
|
||||
if ( get_current_user_id() === $connection['user_ID'] ) {
|
||||
require_lib( 'external-connections' );
|
||||
$connections = \WPCOM_External_Connections::init();
|
||||
return $connections->delete_keyring_connection( $connection['ID'] );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$response = Client::wpcom_json_api_request_as_user(
|
||||
'/me/connections/' . $connection['ID'],
|
||||
'2',
|
||||
array( 'method' => 'DELETE' )
|
||||
);
|
||||
if ( is_wp_error( $response ) ) {
|
||||
return false;
|
||||
}
|
||||
$body = json_decode( wp_remote_retrieve_body( $response ) );
|
||||
return $body->deleted ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the connection data for the provided service.
|
||||
*
|
||||
* @param string $service The service identifier.
|
||||
* @return array The connection data.
|
||||
*/
|
||||
public static function get_connection_data( $service ) {
|
||||
$connection = self::get_connection( $service );
|
||||
if ( empty( $connection ) ) {
|
||||
return array(
|
||||
'is_connected' => false,
|
||||
'account_name' => '',
|
||||
'profile_image' => '',
|
||||
);
|
||||
}
|
||||
|
||||
$is_connected = isset( $connection['status'] ) && $connection['status'] === 'ok';
|
||||
$account_name = $is_connected ? ( $connection['external_display'] ?? $connection['external_name'] ) : '';
|
||||
$profile_image = $is_connected ? $connection['external_profile_picture'] : '';
|
||||
|
||||
return array(
|
||||
'is_connected' => $is_connected,
|
||||
'account_name' => $account_name,
|
||||
'profile_image' => $profile_image,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers connection settings.
|
||||
*/
|
||||
public static function register_settings() {
|
||||
global $pagenow;
|
||||
$host = new Host();
|
||||
|
||||
if ( ! $host->is_wpcom_simple() ) {
|
||||
$connection = new Connection_Manager( 'jetpack' );
|
||||
$status = new Status();
|
||||
|
||||
if ( $status->is_offline_mode() || ! $connection->has_connected_owner() || ! $connection->is_user_connected() ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( self::$services as $page => $services ) {
|
||||
if ( $pagenow !== "options-$page.php" ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
add_settings_section(
|
||||
'jetpack_external_connections_section',
|
||||
__( 'Integrations', 'jetpack-external-connections' ),
|
||||
'__return_false',
|
||||
$page
|
||||
);
|
||||
|
||||
$asset_name = 'jetpack-external-connections-settings';
|
||||
Assets::register_script(
|
||||
$asset_name,
|
||||
"build/$asset_name/$asset_name.js",
|
||||
self::BASE_FILE,
|
||||
array(
|
||||
'in_footer' => true,
|
||||
'textdomain' => 'jetpack-external-connections',
|
||||
)
|
||||
);
|
||||
Assets::enqueue_script( $asset_name );
|
||||
|
||||
$script_data = array();
|
||||
|
||||
foreach ( $services as $service ) {
|
||||
if ( $host->is_wpcom_platform() ) {
|
||||
$support_link = $service['support_link']['wpcom'];
|
||||
if ( function_exists( 'localized_wpcom_url' ) ) {
|
||||
$support_link = localized_wpcom_url( $support_link );
|
||||
}
|
||||
} else {
|
||||
$support_link = Redirect::get_url( $service['support_link']['jetpack'] );
|
||||
}
|
||||
|
||||
$connect_url = self::get_connect_url( $service['service'] );
|
||||
$connection_data = self::get_connection_data( $service['service'] );
|
||||
|
||||
if ( ( empty( $connect_url ) && ! $connection_data['is_connected'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
add_settings_field(
|
||||
'jetpack_external_connections_field_' . $service['service'],
|
||||
$service['title'],
|
||||
function () use ( $service, $support_link ) {
|
||||
?>
|
||||
<div class="jetpack-external-connection" data-service="<?php echo esc_attr( $service['service'] ); ?>"><em><?php esc_html_e( 'Loading…', 'jetpack-external-connections' ); ?></em></div>
|
||||
<p class="description">
|
||||
<?php echo esc_html( $service['description'] ); ?>
|
||||
<a href="<?php echo esc_url( $support_link ); ?>" target="_blank" data-target="wpcom-help-center"><?php esc_html_e( 'Learn more', 'jetpack-external-connections' ); ?></a>
|
||||
</p>
|
||||
<?php
|
||||
},
|
||||
$page,
|
||||
'jetpack_external_connections_section'
|
||||
);
|
||||
|
||||
$script_data[ $service['service'] ] = array(
|
||||
'accountName' => $connection_data['account_name'],
|
||||
'connectUrl' => $connect_url,
|
||||
'deleteNonce' => wp_create_nonce( 'jetpack_delete_external_connection_' . $service['service'] ),
|
||||
'getNonce' => wp_create_nonce( 'jetpack_get_external_connection_' . $service['service'] ),
|
||||
'isConnected' => $connection_data['is_connected'],
|
||||
'profileImage' => $connection_data['profile_image'],
|
||||
'supportLink' => $support_link,
|
||||
'signupLink' => $service['signup_link'] ?? '',
|
||||
);
|
||||
|
||||
if ( isset( $service['script'] ) ) {
|
||||
Assets::enqueue_script( $service['script'] );
|
||||
}
|
||||
}
|
||||
|
||||
wp_add_inline_script(
|
||||
$asset_name,
|
||||
'const jetpackExternalConnectionsData = ' . wp_json_encode( $script_data, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ) . ';',
|
||||
'before'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the AJAX request to delete an external connection.
|
||||
*/
|
||||
public static function ajax_delete_connection() {
|
||||
if ( ! isset( $_REQUEST['service'] ) ) {
|
||||
// @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
|
||||
wp_send_json( array( 'deleted' => 'false' ), null, JSON_UNESCAPED_SLASHES );
|
||||
}
|
||||
|
||||
$service = sanitize_text_field( wp_unslash( $_REQUEST['service'] ) );
|
||||
check_ajax_referer( 'jetpack_delete_external_connection_' . $service );
|
||||
|
||||
$is_deleted = self::delete_connection( $service );
|
||||
// @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
|
||||
wp_send_json( array( 'deleted' => $is_deleted ), null, JSON_UNESCAPED_SLASHES );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the AJAX request to delete an external connection.
|
||||
*/
|
||||
public static function ajax_get_connection() {
|
||||
if ( ! isset( $_REQUEST['service'] ) ) {
|
||||
// @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
|
||||
wp_send_json( array( 'isConnected' => 'false' ), null, JSON_UNESCAPED_SLASHES );
|
||||
}
|
||||
|
||||
$service = sanitize_text_field( wp_unslash( $_REQUEST['service'] ) );
|
||||
check_ajax_referer( 'jetpack_get_external_connection_' . $service );
|
||||
|
||||
$connection_data = self::get_connection_data( $service );
|
||||
wp_send_json(
|
||||
array(
|
||||
'accountName' => $connection_data['account_name'],
|
||||
'isConnected' => $connection_data['is_connected'],
|
||||
'profileImage' => $connection_data['profile_image'],
|
||||
),
|
||||
null, // @phan-suppress-current-line PhanTypeMismatchArgumentProbablyReal -- It takes null, but its phpdoc only says int.
|
||||
JSON_UNESCAPED_SLASHES
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers settings and hooks for a specified service on a given admin page.
|
||||
*
|
||||
* @param string $page The identifier of the admin page where the service settings are added.
|
||||
* @param array $service The service to be associated with the specified admin page.
|
||||
*/
|
||||
public static function add_settings_for_service( $page, $service ) {
|
||||
self::$services[ $page ][] = $service;
|
||||
|
||||
if ( ! has_action( 'admin_init', array( __CLASS__, 'register_settings' ) ) ) {
|
||||
add_action( 'admin_init', array( __CLASS__, 'register_settings' ), 15 );
|
||||
}
|
||||
|
||||
if ( ! has_action( 'wp_ajax_jetpack_delete_external_connection', array( __CLASS__, 'ajax_delete_connection' ) ) ) {
|
||||
add_action( 'wp_ajax_jetpack_delete_external_connection', array( __CLASS__, 'ajax_delete_connection' ) );
|
||||
}
|
||||
|
||||
if ( ! has_action( 'wp_ajax_jetpack_get_external_connection', array( __CLASS__, 'ajax_get_connection' ) ) ) {
|
||||
add_action( 'wp_ajax_jetpack_get_external_connection', array( __CLASS__, 'ajax_get_connection' ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
/* global jetpackExternalConnectionsData */
|
||||
|
||||
import requestExternalAccess from '@automattic/request-external-access';
|
||||
import domReady from '@wordpress/dom-ready';
|
||||
import { useState } from '@wordpress/element';
|
||||
import { applyFilters } from '@wordpress/hooks';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
const fetchData = async params => {
|
||||
const response = await fetch( '/wp-admin/admin-ajax.php', {
|
||||
method: 'POST',
|
||||
body: new URLSearchParams( params ),
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
},
|
||||
} );
|
||||
|
||||
return await response.json();
|
||||
};
|
||||
|
||||
/**
|
||||
* Represents an external connection component for a given service,
|
||||
* allowing users to connect or disconnect from it.
|
||||
*
|
||||
* @param {object} props - The properties for the ExternalConnection component.
|
||||
* @param {string} props.service - The name of the service to be connected or disconnected.
|
||||
* @return {import('react').Component} The ExternalConnection component.
|
||||
*/
|
||||
function ExternalConnection( { service } ) {
|
||||
const config = jetpackExternalConnectionsData[ service ];
|
||||
const [ isConnected, setIsConnected ] = useState( config.isConnected );
|
||||
const [ accountName, setAccountName ] = useState( config.accountName );
|
||||
const [ profileImage, setProfileImage ] = useState( config.profileImage );
|
||||
const [ isTogglingConnection, setTogglingConnection ] = useState( false );
|
||||
|
||||
const toggleConnection = async () => {
|
||||
setTogglingConnection( true );
|
||||
|
||||
if ( isConnected ) {
|
||||
const data = await fetchData( {
|
||||
action: 'jetpack_delete_external_connection',
|
||||
service,
|
||||
_ajax_nonce: config.deleteNonce,
|
||||
} );
|
||||
setTogglingConnection( false );
|
||||
if ( data.deleted ) {
|
||||
setIsConnected( false );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
requestExternalAccess( config.connectUrl, async ( { keyring_id: keyringId } ) => {
|
||||
if ( ! keyringId ) {
|
||||
setTogglingConnection( false );
|
||||
}
|
||||
|
||||
const data = await fetchData( {
|
||||
action: 'jetpack_get_external_connection',
|
||||
service,
|
||||
_ajax_nonce: config.getNonce,
|
||||
} );
|
||||
setIsConnected( data.isConnected );
|
||||
setAccountName( data.accountName );
|
||||
setProfileImage( data.profileImage );
|
||||
setTogglingConnection( false );
|
||||
} );
|
||||
};
|
||||
|
||||
let buttonText;
|
||||
if ( isTogglingConnection ) {
|
||||
buttonText = isConnected
|
||||
? __( 'Disconnecting…', 'jetpack-external-connections' )
|
||||
: __(
|
||||
'Connecting…',
|
||||
'jetpack-external-connections',
|
||||
/* dummy arg to avoid bad minification */ 0
|
||||
);
|
||||
} else {
|
||||
buttonText = isConnected
|
||||
? __( 'Disconnect', 'jetpack-external-connections' )
|
||||
: __(
|
||||
'Connect',
|
||||
'jetpack-external-connections',
|
||||
/* dummy arg to avoid bad minification */ 0
|
||||
);
|
||||
}
|
||||
|
||||
const ExtraSettings = applyFilters( 'jetpack.externalConnections.extraSettings', null, service );
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="jetpack-external-connection-settings">
|
||||
{ isConnected && accountName && (
|
||||
<>
|
||||
{ __( 'Connected as:', 'jetpack-external-connections' ) }
|
||||
{ profileImage && <img src={ profileImage } alt="" /> }
|
||||
<strong>{ accountName } </strong>
|
||||
</>
|
||||
) }
|
||||
{ ! isConnected && config.signupLink && (
|
||||
<a
|
||||
className={ `button-secondary ${ isTogglingConnection ? 'disabled' : '' }` }
|
||||
href={ config.signupLink }
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{ __( 'Sign up', 'jetpack-external-connections' ) }
|
||||
</a>
|
||||
) }
|
||||
<button
|
||||
className="button-secondary"
|
||||
type="button"
|
||||
onClick={ toggleConnection }
|
||||
disabled={ isTogglingConnection }
|
||||
>
|
||||
{ buttonText }
|
||||
</button>
|
||||
</div>
|
||||
{ ExtraSettings && <ExtraSettings isConnected={ isConnected } /> }
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
domReady( () => {
|
||||
const connections = document.querySelectorAll( '.jetpack-external-connection' );
|
||||
if ( ! connections.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
connections.forEach( connection => {
|
||||
const root = createRoot( connection );
|
||||
const service = connection.dataset.service;
|
||||
root.render( <ExternalConnection service={ service } /> );
|
||||
} );
|
||||
} );
|
||||
Reference in New Issue
Block a user