diff --git a/projects/packages/connection/changelog/add-connection-abilities b/projects/packages/connection/changelog/add-connection-abilities new file mode 100644 index 00000000000..40953b0e7ef --- /dev/null +++ b/projects/packages/connection/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: minor +Type: added + +Abilities API: add jetpack-connection/get-connection-status read ability. diff --git a/projects/packages/connection/composer.json b/projects/packages/connection/composer.json index 6e6967807bf..4f5da2919b1 100644 --- a/projects/packages/connection/composer.json +++ b/projects/packages/connection/composer.json @@ -19,6 +19,7 @@ "brain/monkey": "^2.6.2", "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev" }, "suggest": { diff --git a/projects/packages/connection/src/abilities/class-connection-abilities.php b/projects/packages/connection/src/abilities/class-connection-abilities.php new file mode 100644 index 00000000000..7c36cc1d05b --- /dev/null +++ b/projects/packages/connection/src/abilities/class-connection-abilities.php @@ -0,0 +1,217 @@ + 'Jetpack Connection', + 'description' => __( 'Abilities for inspecting the site\'s Jetpack connection state.', 'jetpack-connection' ), + ); + } + + /** + * {@inheritDoc} + */ + public static function get_abilities(): array { + return array( + 'jetpack-connection/get-connection-status' => self::spec_get_connection_status(), + ); + } + + /* + --------------------------------------------------------------------- + * Ability specs + * --------------------------------------------------------------------- + */ + + /** + * Spec: jetpack-connection/get-connection-status. + */ + private static function spec_get_connection_status(): array { + return array( + 'label' => __( 'Get Jetpack connection status', 'jetpack-connection' ), + 'description' => __( + 'Return the site-level Jetpack connection state in one zero-argument call. Shape: { site_connected, user_connected, master_user, plan_class, blog_id, registration_url, jetpack_version }. `site_connected` is true when the site has a blog id and a blog token. `user_connected` is true when at least one user has linked their WordPress.com account. `master_user` is the local user id of the connection owner (the user who registered the site), or null if there is no owner. `plan_class` is the slug of the currently active Jetpack/WordPress.com plan (e.g. "free", "personal", "premium", "business"), or null when no plan is known. `blog_id` is the WordPress.com site id, or null when the site has not been registered. `registration_url` is the wp-admin URL the site owner should visit to register the site when `site_connected` is false; null once the site is connected. `jetpack_version` is the running Jetpack plugin version, or null when the constant is not defined. Read-only and idempotent — safe to poll.', + 'jetpack-connection' + ), + 'input_schema' => array( + 'type' => 'object', + 'properties' => new \stdClass(), + 'additionalProperties' => false, + ), + 'output_schema' => array( + 'type' => 'object', + 'properties' => array( + 'site_connected' => array( 'type' => 'boolean' ), + 'user_connected' => array( 'type' => 'boolean' ), + 'master_user' => array( 'type' => array( 'integer', 'null' ) ), + 'plan_class' => array( 'type' => array( 'string', 'null' ) ), + 'blog_id' => array( 'type' => array( 'integer', 'null' ) ), + 'registration_url' => array( 'type' => array( 'string', 'null' ) ), + 'jetpack_version' => array( 'type' => array( 'string', 'null' ) ), + ), + ), + 'execute_callback' => array( __CLASS__, 'get_connection_status' ), + 'permission_callback' => array( __CLASS__, 'can_view_connection' ), + 'meta' => array( + 'annotations' => array( + 'readonly' => true, + 'destructive' => false, + 'idempotent' => true, + ), + 'show_in_rest' => true, + ), + ); + } + + /* + --------------------------------------------------------------------- + * Permission callbacks + * --------------------------------------------------------------------- + */ + + /** + * Permission check: any authenticated user can read connection state. + * + * Connection state is not sensitive in itself (the same data is exposed + * on the Jetpack admin page and through several existing REST endpoints), + * but anonymous callers have no legitimate need to inspect it, so we + * still require an authenticated request. + * + * @return bool + */ + public static function can_view_connection(): bool { + return is_user_logged_in(); + } + + /* + --------------------------------------------------------------------- + * Execute callbacks + * --------------------------------------------------------------------- + */ + + /** + * Execute: get-connection-status. + * + * @param array|null $input Ignored — zero-arg ability. + * @return array + */ + public static function get_connection_status( $input = null ) { + unset( $input ); + + $manager = self::get_manager(); + $site_connected = (bool) $manager->is_connected(); + $user_connected = (bool) $manager->has_connected_user(); + + $master_user_raw = Jetpack_Options::get_option( 'master_user' ); + $master_user = is_numeric( $master_user_raw ) && (int) $master_user_raw > 0 ? (int) $master_user_raw : null; + + $blog_id_raw = Jetpack_Options::get_option( 'id' ); + $blog_id = is_numeric( $blog_id_raw ) && (int) $blog_id_raw > 0 ? (int) $blog_id_raw : null; + + // The active plan is stored by the Jetpack plugin under `jetpack_active_plan`, + // not as one of the connection package's own option names — read it directly + // from the options table. Absent on connection-only consumers (Boost, Search, + // etc.), in which case `plan_class` is null. + $plan = get_option( 'jetpack_active_plan' ); + $plan_slug = is_array( $plan ) && isset( $plan['product_slug'] ) && is_string( $plan['product_slug'] ) && '' !== $plan['product_slug'] + ? (string) $plan['product_slug'] + : null; + + $jetpack_version_raw = Constants::get_constant( 'JETPACK__VERSION' ); + $jetpack_version = is_string( $jetpack_version_raw ) && '' !== $jetpack_version_raw ? $jetpack_version_raw : null; + + return array( + 'site_connected' => $site_connected, + 'user_connected' => $user_connected, + 'master_user' => $master_user, + 'plan_class' => $plan_slug, + 'blog_id' => $blog_id, + 'registration_url' => $site_connected ? null : self::registration_url(), + 'jetpack_version' => $jetpack_version, + ); + } + + /* + --------------------------------------------------------------------- + * Helpers + * --------------------------------------------------------------------- + */ + + /** + * Return a Connection_Manager instance. Filterable for tests so they can + * inject a partial mock without having to seed Jetpack_Options + tokens. + * + * @return Connection_Manager + */ + protected static function get_manager(): Connection_Manager { + /** + * Filters the Connection_Manager instance used by the Connection abilities. + * + * Tests inject a partial mock here; production callers should leave + * the default. The filter callback receives the package-default + * instance and must return a Connection_Manager — non-Manager + * returns are discarded. + * + * @since 8.4.0 + * + * @param Connection_Manager $manager The default instance. + */ + $instance = apply_filters( 'jetpack_connection_abilities_manager', new Connection_Manager() ); + return $instance instanceof Connection_Manager ? $instance : new Connection_Manager(); + } + + /** + * Build the wp-admin URL the site owner should visit to register the + * site to WordPress.com. We deliberately return a stable admin URL (no + * secret generation, no XML-RPC roundtrip) so this read stays side-effect + * free and cheap to poll. The Jetpack admin page handles the actual + * registration handshake from there. + * + * @return string + */ + private static function registration_url(): string { + return admin_url( 'admin.php?page=jetpack' ); + } +} diff --git a/projects/packages/connection/tests/php/abilities/Connection_Abilities_Test.php b/projects/packages/connection/tests/php/abilities/Connection_Abilities_Test.php new file mode 100644 index 00000000000..e3f277798c9 --- /dev/null +++ b/projects/packages/connection/tests/php/abilities/Connection_Abilities_Test.php @@ -0,0 +1,398 @@ +deregister_category_and_abilities(); + } + + WorDBless_Users::init()->clear_all_users(); + WorDBless_Options::init()->clear_options(); + Constants::clear_constants(); + } + + /** + * Remove our category + abilities from the registry so tests don't leak. + */ + private function deregister_category_and_abilities(): void { + if ( function_exists( 'wp_has_ability' ) && function_exists( 'wp_unregister_ability' ) ) { + foreach ( array_keys( Connection_Abilities::get_abilities() ) as $slug ) { + if ( wp_has_ability( $slug ) ) { + wp_unregister_ability( $slug ); + } + } + } + if ( function_exists( 'wp_has_ability_category' ) && function_exists( 'wp_unregister_ability_category' ) ) { + if ( wp_has_ability_category( Connection_Abilities::CATEGORY_SLUG ) ) { + wp_unregister_ability_category( Connection_Abilities::CATEGORY_SLUG ); + } + } + } + + /** + * Push an entry on `$wp_current_filter` so `doing_action()` reports true + * for the duration of the callback, then pop it back off. + * + * @param string $action Action name to simulate. + * @param callable $fn Callable to run while the action is "firing". + */ + private function with_simulated_action( string $action, callable $fn ): void { + global $wp_current_filter; + $wp_current_filter[] = $action; + try { + $fn(); + } finally { + for ( $i = count( $wp_current_filter ) - 1; $i >= 0; $i-- ) { + if ( $wp_current_filter[ $i ] === $action ) { + array_splice( $wp_current_filter, $i, 1 ); + break; + } + } + } + } + + /** + * Inject a stub Connection_Manager via the filter the abilities use. + * + * @param array $methods Map of method name => return value. + * @return Connection_Manager + */ + private function inject_manager_mock( array $methods ): Connection_Manager { + $stub = $this->createStub( Connection_Manager::class ); + foreach ( $methods as $method => $return ) { + $stub->method( $method )->willReturn( $return ); + } + add_filter( + 'jetpack_connection_abilities_manager', + static function () use ( $stub ) { + return $stub; + } + ); + return $stub; + } + + // --- Abstract getters --------------------------------------------------. + + /** + * The category slug must be the namespaced "jetpack-connection". + */ + public function test_category_slug_is_jetpack_connection(): void { + $this->assertSame( 'jetpack-connection', Connection_Abilities::get_category_slug() ); + } + + /** + * The category definition must include both a label and description. + */ + public function test_category_definition_has_label_and_description(): void { + $def = Connection_Abilities::get_category_definition(); + $this->assertArrayHasKey( 'label', $def ); + $this->assertArrayHasKey( 'description', $def ); + $this->assertNotSame( '', $def['label'] ); + $this->assertNotSame( '', $def['description'] ); + } + + /** + * The abilities map must list exactly the single read ability we ship in this PR. + */ + public function test_abilities_map_lists_the_single_read_ability(): void { + $abilities = Connection_Abilities::get_abilities(); + $this->assertSame( + array( + 'jetpack-connection/get-connection-status', + ), + array_keys( $abilities ) + ); + } + + /** + * Specs must not set their own `category` — Registrar auto-injects it. + */ + public function test_no_spec_sets_category_explicitly(): void { + foreach ( Connection_Abilities::get_abilities() as $slug => $spec ) { + $this->assertArrayNotHasKey( + 'category', + $spec, + "Ability {$slug} should not set its own category — Registrar injects it." + ); + } + } + + /** + * Every spec must declare execute, permission, and read-only annotations. + */ + public function test_every_spec_declares_annotations_permission_and_execute(): void { + foreach ( Connection_Abilities::get_abilities() as $slug => $spec ) { + $this->assertArrayHasKey( 'execute_callback', $spec, "Ability {$slug} missing execute_callback" ); + $this->assertIsCallable( $spec['execute_callback'], "Ability {$slug} execute_callback not callable" ); + $this->assertArrayHasKey( 'permission_callback', $spec, "Ability {$slug} missing permission_callback" ); + $this->assertIsCallable( $spec['permission_callback'], "Ability {$slug} permission_callback not callable" ); + $this->assertArrayHasKey( 'meta', $spec ); + $this->assertArrayHasKey( 'annotations', $spec['meta'] ); + $this->assertTrue( $spec['meta']['annotations']['readonly'], "Ability {$slug} must be readonly" ); + $this->assertFalse( $spec['meta']['annotations']['destructive'], "Ability {$slug} must not be destructive" ); + $this->assertTrue( $spec['meta']['annotations']['idempotent'], "Ability {$slug} must be idempotent" ); + } + } + + // --- Registrar wiring --------------------------------------------------. + + /** + * When the `jetpack_wp_abilities_enabled` filter returns false, `init()` + * must register nothing (no category, no abilities, no hooks). + */ + public function test_init_registers_nothing_when_gate_filter_is_false(): void { + remove_filter( 'jetpack_wp_abilities_enabled', '__return_true' ); + add_filter( 'jetpack_wp_abilities_enabled', '__return_false' ); + + Connection_Abilities::init(); + + $this->assertFalse( + has_action( 'wp_abilities_api_categories_init', array( Connection_Abilities::class, 'register_category' ) ), + 'Category registration must not be hooked when the gate filter is false.' + ); + $this->assertFalse( + has_action( 'wp_abilities_api_init', array( Connection_Abilities::class, 'register_abilities' ) ), + 'Ability registration must not be hooked when the gate filter is false.' + ); + + remove_filter( 'jetpack_wp_abilities_enabled', '__return_false' ); + } + + /** + * When the gate filter returns true and the Abilities API lifecycle + * actions have not yet fired, `init()` must hook both of them. + */ + public function test_init_hooks_both_lifecycle_actions_when_gate_filter_is_true(): void { + Connection_Abilities::init(); + + $this->assertNotFalse( + has_action( 'wp_abilities_api_categories_init', array( Connection_Abilities::class, 'register_category' ) ), + 'Category registration must be hooked when the gate filter is true.' + ); + $this->assertNotFalse( + has_action( 'wp_abilities_api_init', array( Connection_Abilities::class, 'register_abilities' ) ), + 'Ability registration must be hooked when the gate filter is true.' + ); + } + + /** + * `jetpack_wp_abilities_should_register` short-circuits per-ability + * registration when the filter returns false. + */ + public function test_register_abilities_skips_when_should_register_filter_returns_false(): void { + // Deny every slug. + add_filter( 'jetpack_wp_abilities_should_register', '__return_false' ); + + $registered = array(); + $capture = static function ( $slug ) use ( &$registered ) { + $registered[] = $slug; + return false; + }; + + $this->with_simulated_action( + 'wp_abilities_api_init', + function () use ( $capture ) { + // Stub the registration function so we can observe what would be registered. + if ( ! function_exists( 'wp_register_ability' ) ) { + $this->markTestSkipped( 'wp_register_ability not available in this WordPress build.' ); + } + // We cannot redefine the function; instead, rely on the should_register + // filter to short-circuit BEFORE wp_register_ability is called and + // assert via the filter that no ability slugs got through. + add_filter( + 'jetpack_wp_abilities_should_register', + $capture, + 11, + 3 + ); + + Connection_Abilities::register_abilities(); + } + ); + + // The capture filter ran for each ability, but `should_register` returned + // false on the earlier (priority-10) filter, so no slug should have been + // passed through. We rely on no abilities being registered as the assertion. + foreach ( array_keys( Connection_Abilities::get_abilities() ) as $slug ) { + $this->assertFalse( + function_exists( 'wp_has_ability' ) && wp_has_ability( $slug ), + "Ability {$slug} must NOT register when should_register returns false." + ); + } + + remove_filter( 'jetpack_wp_abilities_should_register', '__return_false' ); + remove_filter( 'jetpack_wp_abilities_should_register', $capture, 11 ); + } + + /** + * The Registrar must auto-inject this subclass's `CATEGORY_SLUG` on every + * registered ability whose spec omits `category`. + */ + public function test_category_auto_injection_on_registered_abilities(): void { + if ( ! function_exists( 'wp_register_ability' ) || ! function_exists( 'wp_get_ability' ) ) { + $this->markTestSkipped( 'Abilities API not available in this WordPress build.' ); + } + + $this->with_simulated_action( + 'wp_abilities_api_categories_init', + function () { + Connection_Abilities::register_category(); + } + ); + + $this->with_simulated_action( + 'wp_abilities_api_init', + function () { + Connection_Abilities::register_abilities(); + } + ); + + foreach ( array_keys( Connection_Abilities::get_abilities() ) as $slug ) { + $ability = wp_get_ability( $slug ); + $this->assertNotNull( $ability, "Ability {$slug} should have been registered." ); + $this->assertSame( + Connection_Abilities::CATEGORY_SLUG, + $ability->get_category(), + "Registrar must auto-inject the category slug on {$slug}." + ); + } + } + + // --- Permission callbacks ----------------------------------------------. + + /** + * `can_view_connection()` must deny anonymous (logged-out) callers. + */ + public function test_can_view_connection_denies_anonymous_user(): void { + wp_set_current_user( 0 ); + $this->assertFalse( Connection_Abilities::can_view_connection() ); + } + + /** + * Any authenticated user (even a subscriber) may read connection state. + */ + public function test_can_view_connection_allows_logged_in_user(): void { + $user_id = wp_insert_user( + array( + 'user_login' => 'connection_abilities_subscriber', + 'user_pass' => 'pw', + 'role' => 'subscriber', + ) + ); + wp_set_current_user( (int) $user_id ); + + $this->assertTrue( Connection_Abilities::can_view_connection() ); + } + + // --- get-connection-status execute -------------------------------------. + + /** + * With no options set and a disconnected Manager stub, the read must + * return the documented zero state and a non-empty `registration_url`. + */ + public function test_get_connection_status_returns_disconnected_state_by_default(): void { + $this->inject_manager_mock( + array( + 'is_connected' => false, + 'has_connected_user' => false, + ) + ); + + $out = Connection_Abilities::get_connection_status(); + + $this->assertIsArray( $out ); + $this->assertFalse( $out['site_connected'] ); + $this->assertFalse( $out['user_connected'] ); + $this->assertNull( $out['master_user'] ); + $this->assertNull( $out['plan_class'] ); + $this->assertNull( $out['blog_id'] ); + $this->assertIsString( $out['registration_url'] ); + $this->assertNotSame( '', $out['registration_url'] ); + $this->assertNull( $out['jetpack_version'] ); + } + + /** + * With a connected Manager stub and the full set of options populated, + * the read must surface blog_id, master_user, plan_class and version, + * and return a null `registration_url` (the site is already connected). + */ + public function test_get_connection_status_reports_connected_state_with_options_set(): void { + $this->inject_manager_mock( + array( + 'is_connected' => true, + 'has_connected_user' => true, + ) + ); + Jetpack_Options::update_option( 'id', 12345 ); + Jetpack_Options::update_option( 'master_user', 42 ); + update_option( 'jetpack_active_plan', array( 'product_slug' => 'jetpack_premium' ) ); + Constants::set_constant( 'JETPACK__VERSION', '99.9' ); + + $out = Connection_Abilities::get_connection_status(); + + $this->assertTrue( $out['site_connected'] ); + $this->assertTrue( $out['user_connected'] ); + $this->assertSame( 42, $out['master_user'] ); + $this->assertSame( 12345, $out['blog_id'] ); + $this->assertSame( 'jetpack_premium', $out['plan_class'] ); + $this->assertNull( $out['registration_url'], 'registration_url must be null once the site is connected.' ); + $this->assertSame( '99.9', $out['jetpack_version'] ); + } +} diff --git a/projects/plugins/automattic-for-agencies-client/changelog/add-connection-abilities b/projects/plugins/automattic-for-agencies-client/changelog/add-connection-abilities new file mode 100644 index 00000000000..c47cb18e829 --- /dev/null +++ b/projects/plugins/automattic-for-agencies-client/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/automattic-for-agencies-client/composer.lock b/projects/plugins/automattic-for-agencies-client/composer.lock index 4c4f8b2f351..64f48ec0b2c 100644 --- a/projects/plugins/automattic-for-agencies-client/composer.lock +++ b/projects/plugins/automattic-for-agencies-client/composer.lock @@ -411,7 +411,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -427,6 +427,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0" diff --git a/projects/plugins/backup/changelog/add-connection-abilities b/projects/plugins/backup/changelog/add-connection-abilities new file mode 100644 index 00000000000..c47cb18e829 --- /dev/null +++ b/projects/plugins/backup/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/backup/composer.lock b/projects/plugins/backup/composer.lock index bac7cfbd08c..d825c82459e 100644 --- a/projects/plugins/backup/composer.lock +++ b/projects/plugins/backup/composer.lock @@ -669,7 +669,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -685,6 +685,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0" diff --git a/projects/plugins/boost/changelog/add-connection-abilities b/projects/plugins/boost/changelog/add-connection-abilities new file mode 100644 index 00000000000..c47cb18e829 --- /dev/null +++ b/projects/plugins/boost/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/boost/composer.lock b/projects/plugins/boost/composer.lock index 5178c4cc4ce..387f7859280 100644 --- a/projects/plugins/boost/composer.lock +++ b/projects/plugins/boost/composer.lock @@ -530,7 +530,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -546,6 +546,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0" diff --git a/projects/plugins/classic-theme-helper-plugin/changelog/add-connection-abilities b/projects/plugins/classic-theme-helper-plugin/changelog/add-connection-abilities new file mode 100644 index 00000000000..c47cb18e829 --- /dev/null +++ b/projects/plugins/classic-theme-helper-plugin/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/classic-theme-helper-plugin/composer.lock b/projects/plugins/classic-theme-helper-plugin/composer.lock index 4439c82deed..b323d8cd36f 100644 --- a/projects/plugins/classic-theme-helper-plugin/composer.lock +++ b/projects/plugins/classic-theme-helper-plugin/composer.lock @@ -596,7 +596,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -612,6 +612,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0" diff --git a/projects/plugins/inspect/changelog/add-connection-abilities b/projects/plugins/inspect/changelog/add-connection-abilities new file mode 100644 index 00000000000..c47cb18e829 --- /dev/null +++ b/projects/plugins/inspect/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/inspect/composer.lock b/projects/plugins/inspect/composer.lock index 9ba95d795cc..656a1992e80 100644 --- a/projects/plugins/inspect/composer.lock +++ b/projects/plugins/inspect/composer.lock @@ -411,7 +411,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -427,6 +427,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0" diff --git a/projects/plugins/jetpack/changelog/add-connection-abilities b/projects/plugins/jetpack/changelog/add-connection-abilities new file mode 100644 index 00000000000..5a1442318bd --- /dev/null +++ b/projects/plugins/jetpack/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: minor +Type: enhancement + +Abilities API: register the jetpack-connection/get-connection-status read ability from the Jetpack plugin. diff --git a/projects/plugins/jetpack/class.jetpack.php b/projects/plugins/jetpack/class.jetpack.php index 72eaa5ae5d6..377cb4767b1 100644 --- a/projects/plugins/jetpack/class.jetpack.php +++ b/projects/plugins/jetpack/class.jetpack.php @@ -758,6 +758,11 @@ function () { // Register Jetpack module management abilities (WordPress Abilities API, WP 6.9+). \Automattic\Jetpack\Plugin\Abilities\Modules_Abilities::init(); + + // Register Connection abilities (WordPress Abilities API, WP 6.9+). Scoped to the + // Jetpack plugin for now: the Connection package no longer auto-wires these, so + // connection-only consumers (Boost, Protect, Search, etc.) do not register them yet. + \Automattic\Jetpack\Connection\Abilities\Connection_Abilities::init(); } /** diff --git a/projects/plugins/jetpack/composer.lock b/projects/plugins/jetpack/composer.lock index 540c4862a0a..30467f4b43e 100644 --- a/projects/plugins/jetpack/composer.lock +++ b/projects/plugins/jetpack/composer.lock @@ -1097,7 +1097,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -1113,6 +1113,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0" diff --git a/projects/plugins/mu-wpcom-plugin/changelog/add-connection-abilities b/projects/plugins/mu-wpcom-plugin/changelog/add-connection-abilities new file mode 100644 index 00000000000..c47cb18e829 --- /dev/null +++ b/projects/plugins/mu-wpcom-plugin/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/mu-wpcom-plugin/composer.lock b/projects/plugins/mu-wpcom-plugin/composer.lock index c9860b76808..1cf92402e5c 100644 --- a/projects/plugins/mu-wpcom-plugin/composer.lock +++ b/projects/plugins/mu-wpcom-plugin/composer.lock @@ -566,7 +566,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -582,6 +582,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0" diff --git a/projects/plugins/paypal-payment-buttons/changelog/add-connection-abilities b/projects/plugins/paypal-payment-buttons/changelog/add-connection-abilities new file mode 100644 index 00000000000..c47cb18e829 --- /dev/null +++ b/projects/plugins/paypal-payment-buttons/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/paypal-payment-buttons/composer.lock b/projects/plugins/paypal-payment-buttons/composer.lock index f65127687cd..7af9f3aa980 100644 --- a/projects/plugins/paypal-payment-buttons/composer.lock +++ b/projects/plugins/paypal-payment-buttons/composer.lock @@ -396,7 +396,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -412,6 +412,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0" diff --git a/projects/plugins/protect/changelog/add-connection-abilities b/projects/plugins/protect/changelog/add-connection-abilities new file mode 100644 index 00000000000..c47cb18e829 --- /dev/null +++ b/projects/plugins/protect/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/protect/composer.lock b/projects/plugins/protect/composer.lock index a312235d7f4..1948d547cf4 100644 --- a/projects/plugins/protect/composer.lock +++ b/projects/plugins/protect/composer.lock @@ -652,7 +652,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -668,6 +668,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0" diff --git a/projects/plugins/search/changelog/add-connection-abilities b/projects/plugins/search/changelog/add-connection-abilities new file mode 100644 index 00000000000..c47cb18e829 --- /dev/null +++ b/projects/plugins/search/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/search/composer.lock b/projects/plugins/search/composer.lock index 16f37ff4241..219b1a3089f 100644 --- a/projects/plugins/search/composer.lock +++ b/projects/plugins/search/composer.lock @@ -530,7 +530,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -546,6 +546,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0" diff --git a/projects/plugins/social/changelog/add-connection-abilities b/projects/plugins/social/changelog/add-connection-abilities new file mode 100644 index 00000000000..c47cb18e829 --- /dev/null +++ b/projects/plugins/social/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/social/composer.lock b/projects/plugins/social/composer.lock index 4ba09870934..ad2ec520a3a 100644 --- a/projects/plugins/social/composer.lock +++ b/projects/plugins/social/composer.lock @@ -593,7 +593,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -609,6 +609,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0" diff --git a/projects/plugins/starter-plugin/changelog/add-connection-abilities b/projects/plugins/starter-plugin/changelog/add-connection-abilities new file mode 100644 index 00000000000..c47cb18e829 --- /dev/null +++ b/projects/plugins/starter-plugin/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/starter-plugin/composer.lock b/projects/plugins/starter-plugin/composer.lock index 92c8e5b6ee4..c1c91f298ae 100644 --- a/projects/plugins/starter-plugin/composer.lock +++ b/projects/plugins/starter-plugin/composer.lock @@ -530,7 +530,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -546,6 +546,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0" diff --git a/projects/plugins/videopress/changelog/add-connection-abilities b/projects/plugins/videopress/changelog/add-connection-abilities new file mode 100644 index 00000000000..c47cb18e829 --- /dev/null +++ b/projects/plugins/videopress/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/videopress/composer.lock b/projects/plugins/videopress/composer.lock index 9f04068508b..2f1f6b3f0b5 100644 --- a/projects/plugins/videopress/composer.lock +++ b/projects/plugins/videopress/composer.lock @@ -530,7 +530,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -546,6 +546,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0" diff --git a/projects/plugins/wpcloud-sso/changelog/add-connection-abilities b/projects/plugins/wpcloud-sso/changelog/add-connection-abilities new file mode 100644 index 00000000000..c47cb18e829 --- /dev/null +++ b/projects/plugins/wpcloud-sso/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/wpcloud-sso/composer.lock b/projects/plugins/wpcloud-sso/composer.lock index 8dabfd6b208..950372fdb0b 100644 --- a/projects/plugins/wpcloud-sso/composer.lock +++ b/projects/plugins/wpcloud-sso/composer.lock @@ -411,7 +411,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -427,6 +427,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0" diff --git a/projects/plugins/wpcomsh/changelog/add-connection-abilities b/projects/plugins/wpcomsh/changelog/add-connection-abilities new file mode 100644 index 00000000000..c47cb18e829 --- /dev/null +++ b/projects/plugins/wpcomsh/changelog/add-connection-abilities @@ -0,0 +1,4 @@ +Significance: patch +Type: changed + +Updated package dependencies. diff --git a/projects/plugins/wpcomsh/composer.lock b/projects/plugins/wpcomsh/composer.lock index 3a5499ef29e..51e3158d8fa 100644 --- a/projects/plugins/wpcomsh/composer.lock +++ b/projects/plugins/wpcomsh/composer.lock @@ -773,7 +773,7 @@ "dist": { "type": "path", "url": "../../packages/connection", - "reference": "37cff8191289fa89742688ce970f25f702cb6ba8" + "reference": "30612a3e27b0391db94d602d42cd765a27985abf" }, "require": { "automattic/jetpack-a8c-mc-stats": "@dev", @@ -789,6 +789,7 @@ "automattic/jetpack-licensing": "@dev", "automattic/jetpack-sync": "@dev", "automattic/jetpack-test-environment": "@dev", + "automattic/jetpack-wp-abilities": "@dev", "automattic/phpunit-select-config": "@dev", "brain/monkey": "^2.6.2", "yoast/phpunit-polyfills": "^4.0.0"