← 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' ); |