PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.7
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.7
16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 All 506 releases
← All changes | _inc/lib/core-api/wpcom-endpoints/class-wpcom-rest-api-v2-endpoint-ai-feature-settings.php +27 -44 16.2-beta → 16.3-a.7 View file →
@@ -9,15 +9,10 @@
9 9 * POST — accepts a partial update ({ master_enabled, features }) and writes
10 10 * the site-local options backing the toggles. Returns the fresh GET
11 11 * shape.
12 12 *
13 - * Unlike the MCP settings endpoint, nothing here proxies to WPCOM: the
14 - * settings are site-local wp_options, so the endpoint works the same on
15 - * Atomic and self-hosted sites. On WordPress.com Simple the route does not
16 - * register at all — Simple keeps the existing wp.com settings contract, and
17 - * with core settings REST also refusing these options there, the new
18 - * per-feature options stay unwritten on Simple while the reused SEO/Search
19 - * options keep their existing owning surfaces.
13 + * Toggles use site-local options; SEO settings access uses the cached WordPress.com site record.
14 + * WordPress.com Simple keeps its existing settings endpoint.
20 15 *
21 16 * @package automattic/jetpack
22 17 */
23 18
@@ -24,9 +19,8 @@
24 19 use Automattic\Jetpack\Connection\Manager;
25 20 use Automattic\Jetpack\Current_Plan;
26 21 use Automattic\Jetpack\Search\Plan as Search_Plan;
27 22 use Automattic\Jetpack\SEO\Ai_Seo;
28 -use Automattic\Jetpack\Status;
29 23 use Automattic\Jetpack\Status\Host;
30 24
31 25 if ( ! defined( 'ABSPATH' ) ) {
32 26 exit( 0 );
@@ -229,9 +223,10 @@
229 223 *
230 224 * @return array
231 225 */
232 226 private function build_settings_response() {
233 - $search_plan = class_exists( Search_Plan::class ) ? new Search_Plan() : null;
227 + $search_plan = class_exists( Search_Plan::class ) ? new Search_Plan() : null;
228 + $is_connected = Jetpack_AI_Settings::site_is_connected();
234 229
235 230 // Entitlement: the plan includes some Search product (Classic or Instant).
236 231 $supports_search = $search_plan && $search_plan->supports_search();
237 232
@@ -249,10 +244,10 @@
249 244 }
250 245
251 246 return array(
252 247 'host_allows_ai' => Jetpack_AI_Settings::host_allows_ai(),
253 - 'is_connected' => $this->is_connected(),
254 - 'is_user_connected' => $this->is_user_connected(),
248 + 'is_connected' => $is_connected,
249 + 'is_user_connected' => Jetpack_AI_Settings::user_is_connected(),
255 250 'plan' => array(
256 251 'supports_ai' => class_exists( Current_Plan::class ) && Current_Plan::supports( 'ai-assistant' ),
257 252 'supports_search' => $supports_search,
258 253 // The free Search tier reports supports_search too, but its
@@ -268,10 +263,11 @@
268 263 'enabled' => $stored['feature_clip'],
269 264 'available' => $this->is_feature_clip_available(),
270 265 ),
271 266 'ai_seo' => array(
272 - 'enabled' => $stored['ai_seo'],
273 - 'available' => $this->is_ai_seo_available(),
267 + 'enabled' => $stored['ai_seo'],
268 + 'available' => $this->is_ai_seo_available(),
269 + 'can_manage' => $is_connected && $this->can_manage_seo(),
274 270 ),
275 271 'ai_search' => array(
276 272 'enabled' => $stored['ai_search'],
277 273 'requires_upgrade' => $ai_search_requires_upgrade,
@@ -280,8 +276,26 @@
280 276 );
281 277 }
282 278
283 279 /**
280 + * Whether the site's active features include SEO settings.
281 + *
282 + * The is_ai_seo_available() check accepts plan defaults, which can report SEO
283 + * support even when site-specific restrictions, such as VIP's, block settings.
284 + *
285 + * @return bool
286 + */
287 + private function can_manage_seo() {
288 + $site_data = ( new Manager( 'jetpack' ) )->get_connected_site_data();
289 + if ( is_wp_error( $site_data ) ) {
290 + return false;
291 + }
292 +
293 + $active_features = $site_data->plan->features->active ?? null;
294 + return is_array( $active_features ) && in_array( 'advanced-seo', $active_features, true );
295 + }
296 +
297 + /**
284 298 * Whether the AI SEO row is available, so the settings page can hide it. The
285 299 * row is offered only where a surface it governs can run: the sidebar's
286 300 * suggestions or the editor's generation.
287 301 *
@@ -321,39 +335,8 @@
321 335 return true;
322 336 }
323 337
324 338 return (bool) \Automattic\Jetpack\Extensions\ImageStudio\is_image_studio_enabled();
325 - }
326 -
327 - /**
328 - * Whether the site can know its plan: Simple sites always can; elsewhere a
329 - * connected owner outside offline mode is required. Mirrors the connection
330 - * predicate the AI feature load points use — offline mode included, since a
331 - * site can hold connection tokens while offline mode keeps every AI surface
332 - * from loading.
333 - *
334 - * @return bool
335 - */
336 - private function is_connected() {
337 - return ( new Host() )->is_wpcom_simple()
338 - || ( ( new Manager( 'jetpack' ) )->has_connected_owner()
339 - && ! ( new Status() )->is_offline_mode() );
340 - }
341 -
342 - /**
343 - * Whether the current user's own account is connected. is_connected() above
344 - * is the site-level gate the feature load points share, but the editor chat
345 - * keys its variant off the requesting user: the agents-manager loader
346 - * downgrades to its disconnected variant when the current user holds no
347 - * token, so the settings page needs this bit to tell an admin whose account
348 - * is not connected that the chat will not run for them. Simple
349 - * short-circuits true, matching is_connected().
350 - *
351 - * @return bool
352 - */
353 - private function is_user_connected() {
354 - return ( new Host() )->is_wpcom_simple()
355 - || ( new Manager( 'jetpack' ) )->is_user_connected();
356 339 }
357 340 }
358 341
359 342 wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Endpoint_AI_Feature_Settings' );