PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 16.1-beta.3
Jetpack – WP Security, Backup, Speed, & Growth v16.1-beta.3
16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / jetpack_vendor / automattic / jetpack-connection / src / abilities / class-connection-abilities.php
jetpack / jetpack_vendor / automattic / jetpack-connection / src / abilities Last commit date
class-connection-abilities.php 2 months ago
class-connection-abilities.php
224 lines
1 <?php
2 /**
3 * Jetpack Connection Abilities Registration.
4 *
5 * Registers Jetpack Connection abilities with the WordPress Abilities API so
6 * AI agents can inspect the site's connection state through the standard
7 * `wp-abilities/v1` REST surface.
8 *
9 * @package automattic/jetpack-connection
10 */
11
12 // @phan-file-suppress PhanUndeclaredFunction, PhanUndeclaredClassMethod @phan-suppress-current-line UnusedSuppression -- Abilities API added in WP 6.9; suppressions needed for older-WP compatibility runs.
13
14 namespace Automattic\Jetpack\Connection\Abilities;
15
16 use Automattic\Jetpack\Connection\Manager as Connection_Manager;
17 use Automattic\Jetpack\Connection\Package_Version;
18 use Automattic\Jetpack\WP_Abilities\Registrar;
19 use Jetpack_Options;
20
21 /**
22 * Registers Jetpack Connection abilities with the WordPress Abilities API.
23 *
24 * Exposes a single read-only ability for site-level connection state so AI
25 * agents can answer "is this site registered?" without having to
26 * reverse-engineer Jetpack_Options keys.
27 *
28 * Writes (registering a new site, disconnecting a user, transferring
29 * ownership) are deliberately deferred to a follow-up PR.
30 */
31 class Connection_Abilities extends Registrar {
32
33 const CATEGORY_SLUG = 'jetpack';
34
35 /**
36 * {@inheritDoc}
37 */
38 public static function get_category_slug(): string {
39 return self::CATEGORY_SLUG;
40 }
41
42 /**
43 * {@inheritDoc}
44 *
45 * The `jetpack` ability-category is shared with other Jetpack registrars
46 * (e.g. the Modules_Abilities class in the Jetpack plugin). Only the first
47 * registration wins, so the English source string is kept byte-identical
48 * across registrars to keep the visible category text consistent
49 * regardless of load order.
50 */
51 public static function get_category_definition(): array {
52 return array(
53 // "Jetpack" is a product name and should not be translated.
54 'label' => 'Jetpack',
55 'description' => __( 'Abilities provided by Jetpack.', 'jetpack-connection' ),
56 );
57 }
58
59 /**
60 * {@inheritDoc}
61 */
62 public static function get_abilities(): array {
63 return array(
64 'jetpack/get-connection-status' => self::spec_get_connection_status(),
65 );
66 }
67
68 /*
69 ---------------------------------------------------------------------
70 * Ability specs
71 * ---------------------------------------------------------------------
72 */
73
74 /**
75 * Spec: jetpack/get-connection-status.
76 */
77 private static function spec_get_connection_status(): array {
78 return array(
79 'label' => __( 'Get Jetpack connection status', 'jetpack-connection' ),
80 'description' => __(
81 'Return the site-level Jetpack connection state in one zero-argument call. Shape: { site_registered, user_connected, master_user, blog_id, registration_url, connection_version }. `site_registered` 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. `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_registered` is false; null once the site is registered. `connection_version` is the running Jetpack Connection package version. Read-only and idempotent — safe to poll.',
82 'jetpack-connection'
83 ),
84 'input_schema' => array(
85 'type' => 'object',
86 'properties' => new \stdClass(),
87 'additionalProperties' => false,
88 ),
89 'output_schema' => array(
90 'type' => 'object',
91 'properties' => array(
92 'site_registered' => array( 'type' => 'boolean' ),
93 'user_connected' => array( 'type' => 'boolean' ),
94 'master_user' => array( 'type' => array( 'integer', 'null' ) ),
95 'blog_id' => array( 'type' => array( 'integer', 'null' ) ),
96 'registration_url' => array( 'type' => array( 'string', 'null' ) ),
97 'connection_version' => array( 'type' => 'string' ),
98 ),
99 ),
100 'execute_callback' => array( __CLASS__, 'get_connection_status' ),
101 'permission_callback' => array( __CLASS__, 'can_view_connection' ),
102 'meta' => array(
103 'annotations' => array(
104 'readonly' => true,
105 'destructive' => false,
106 'idempotent' => true,
107 ),
108 'show_in_rest' => true,
109 'mcp' => array(
110 'public' => true,
111 'type' => 'tool', // default is already "tool", but can be explicit.
112 ),
113 ),
114 );
115 }
116
117 /*
118 ---------------------------------------------------------------------
119 * Permission callbacks
120 * ---------------------------------------------------------------------
121 */
122
123 /**
124 * Permission check: mirrors the capability used by the Jetpack admin page.
125 *
126 * Connection state is not sensitive in itself (the same data is exposed
127 * on the Jetpack admin page and through several existing REST endpoints),
128 * but subscribers and contributors have no legitimate need to inspect it.
129 * Gating on `jetpack_admin_page` aligns with how {@see Modules_Abilities}
130 * scopes its read.
131 *
132 * @return bool
133 */
134 public static function can_view_connection(): bool {
135 return current_user_can( 'jetpack_admin_page' );
136 }
137
138 /*
139 ---------------------------------------------------------------------
140 * Execute callbacks
141 * ---------------------------------------------------------------------
142 */
143
144 /**
145 * Execute: get-connection-status.
146 *
147 * @param array|null $input Ignored — zero-arg ability.
148 * @return array
149 */
150 public static function get_connection_status( $input = null ) {
151 unset( $input );
152
153 $manager = self::get_manager();
154 $site_registered = (bool) $manager->is_connected();
155 $user_connected = (bool) $manager->has_connected_user();
156
157 $master_user_raw = Jetpack_Options::get_option( 'master_user' );
158 $master_user = is_numeric( $master_user_raw ) && (int) $master_user_raw > 0 ? (int) $master_user_raw : null;
159
160 $blog_id_raw = Jetpack_Options::get_option( 'id' );
161 $blog_id = is_numeric( $blog_id_raw ) && (int) $blog_id_raw > 0 ? (int) $blog_id_raw : null;
162
163 return array(
164 'site_registered' => $site_registered,
165 'user_connected' => $user_connected,
166 'master_user' => $master_user,
167 'blog_id' => $blog_id,
168 'registration_url' => $site_registered ? null : self::registration_url(),
169 'connection_version' => Package_Version::PACKAGE_VERSION,
170 );
171 }
172
173 /*
174 ---------------------------------------------------------------------
175 * Helpers
176 * ---------------------------------------------------------------------
177 */
178
179 /**
180 * Return a Connection_Manager instance. Filterable for tests so they can
181 * inject a partial mock without having to seed Jetpack_Options + tokens.
182 *
183 * @return Connection_Manager
184 */
185 protected static function get_manager(): Connection_Manager {
186 /**
187 * Filters the Connection_Manager instance used by the Connection abilities.
188 *
189 * Tests inject a partial mock here; production callers should leave
190 * the default. The filter callback receives the package-default
191 * instance and must return a Connection_Manager — non-Manager
192 * returns are discarded.
193 *
194 * @since 8.4.0
195 *
196 * @param Connection_Manager $manager The default instance.
197 */
198 $instance = apply_filters( 'jetpack_connection_abilities_manager', new Connection_Manager() );
199 return $instance instanceof Connection_Manager ? $instance : new Connection_Manager();
200 }
201
202 /**
203 * Build the wp-admin URL the site owner should visit to register the
204 * site to WordPress.com. We deliberately return a stable admin URL (no
205 * secret generation, no XML-RPC roundtrip) so this read stays side-effect
206 * free and cheap to poll. The destination page handles the actual
207 * registration handshake from there.
208 *
209 * WP 7.0+ ships a core "Connectors" screen at `wp-admin/options-connectors.php`
210 * with a Jetpack card registered by {@see Jetpack_Connector}. We probe
211 * for the file directly (rather than a `class_exists()` on the registry)
212 * because the file is what actually serves the URL — if it isn't on
213 * disk, the redirect 404s regardless of which classes have loaded.
214 *
215 * @return string
216 */
217 private static function registration_url(): string {
218 if ( defined( 'ABSPATH' ) && file_exists( ABSPATH . 'wp-admin/options-connectors.php' ) ) {
219 return admin_url( 'options-connectors.php' );
220 }
221 return admin_url( 'admin.php?page=jetpack' );
222 }
223 }
224