* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. */ public function get_items( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable $options = AMP_Options_Manager::get_options(); $properties = $this->get_item_schema()['properties']; $options = wp_array_slice_assoc( $options, array_keys( $properties ) ); // Add the preview permalink. The permalink can't be handled via AMP_Options_Manager::get_options because // amp_admin_get_preview_permalink calls AMP_Options_Manager::get_options, leading to infinite recursion. $options[ self::PREVIEW_PERMALINK ] = amp_admin_get_preview_permalink(); $options[ self::SUPPRESSIBLE_PLUGINS ] = $this->plugin_suppression->get_suppressible_plugins_with_details(); $options[ self::SUPPORTABLE_POST_TYPES ] = array_map( static function( $slug ) { $post_type = (array) get_post_type_object( $slug ); $post_type['supports_amp'] = post_type_supports( $post_type['name'], AMP_Post_Type_Support::SLUG ); return $post_type; }, AMP_Post_Type_Support::get_eligible_post_types() ); $options[ self::SUPPORTABLE_TEMPLATES ] = $this->get_nested_supportable_templates( AMP_Theme_Support::get_supportable_templates() ); $options[ Option::SUPPRESSED_PLUGINS ] = $this->plugin_suppression->prepare_suppressed_plugins_for_response( $options[ Option::SUPPRESSED_PLUGINS ] ); $options[ self::ONBOARDING_WIZARD_LINK ] = get_admin_url( null, add_query_arg( [ 'page' => OnboardingWizardSubmenu::SCREEN_ID ], 'admin.php' ) ); $options[ self::CUSTOMIZER_LINK ] = amp_get_customizer_url(); /** * Filters options for services to add additional REST items. * * @internal * * @param array $service_options REST Options for Services. */ $service_options = apply_filters( 'amp_rest_options', [] ); if ( ! is_array( $service_options ) ) { $service_options = []; } $options = array_merge( $options, $service_options ); return rest_ensure_response( $options ); } /** * Provides a hierarchical array of supportable templates. * * @param array[] $supportable_templates Template options. * @param string|null $parent_template_id The parent to provide templates for. * @return array[] Supportable templates with nesting. */ private function get_nested_supportable_templates( $supportable_templates, $parent_template_id = null ) { $nested_supportable_templates = []; foreach ( $supportable_templates as $id => $supportable_template ) { if ( $parent_template_id ? empty( $supportable_template['parent'] ) || $parent_template_id !== $supportable_template['parent'] : ! empty( $supportable_template['parent'] ) ) { continue; } // Skip showing an option if it doesn't have a label. if ( empty( $supportable_template['label'] ) ) { continue; } $supportable_template['id'] = $id; $supportable_template['children'] = $this->get_nested_supportable_templates( $supportable_templates, $id ); // Omit obsolete properties. unset( $supportable_template['supported'], $supportable_template['user_supported'], $supportable_template['immutable'] ); $nested_supportable_templates[] = $supportable_template; } return $nested_supportable_templates; } /** * Updates AMP plugin options. * * @param WP_REST_Request $request Full details about the request. * @return array|WP_Error Array on success, or error object on failure. */ public function update_items( $request ) { $params = $request->get_params(); AMP_Options_Manager::update_options( wp_array_slice_assoc( $params, array_keys( $this->get_item_schema()['properties'] ) ) ); return rest_ensure_response( $this->get_items( $request ) ); } /** * Retrieves the schema for plugin options provided by the endpoint. * * @return array Item schema data. */ public function get_item_schema() { if ( ! $this->schema ) { $this->schema = [ '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => 'amp-wp-options', 'type' => 'object', 'properties' => [ // Note: The sanitize_callback from AMP_Options_Manager::register_settings() is applying to this option. Option::THEME_SUPPORT => [ 'type' => 'string', 'enum' => [ AMP_Theme_Support::READER_MODE_SLUG, AMP_Theme_Support::STANDARD_MODE_SLUG, AMP_Theme_Support::TRANSITIONAL_MODE_SLUG, ], ], Option::READER_THEME => [ 'type' => 'string', 'arg_options' => [ 'validate_callback' => function ( $value ) { // Note: The validate_callback is used instead of enum in order to prevent leaking the list of themes. return $this->reader_themes->theme_data_exists( $value ); }, ], ], Option::MOBILE_REDIRECT => [ 'type' => 'boolean', 'default' => false, ], self::PREVIEW_PERMALINK => [ 'type' => 'string', 'readonly' => true, 'format' => 'url', ], Option::PLUGIN_CONFIGURED => [ 'type' => 'boolean', 'default' => false, ], Option::ALL_TEMPLATES_SUPPORTED => [ 'type' => 'boolean', ], Option::SUPPRESSED_PLUGINS => [ 'type' => 'object', ], self::SUPPRESSIBLE_PLUGINS => [ 'type' => 'object', 'readonly' => true, ], Option::SUPPORTED_TEMPLATES => [ 'type' => 'array', 'items' => [ 'type' => 'string', ], ], Option::SUPPORTED_POST_TYPES => [ 'type' => 'array', 'items' => [ 'type' => 'string', ], ], Option::ANALYTICS => [ 'type' => 'object', ], self::SUPPORTABLE_POST_TYPES => [ 'type' => 'array', 'readonly' => true, ], self::SUPPORTABLE_TEMPLATES => [ 'type' => 'array', 'readonly' => true, ], self::ONBOARDING_WIZARD_LINK => [ 'type' => 'url', 'readonly' => true, ], self::CUSTOMIZER_LINK => [ 'type' => 'url', 'readonly' => true, ], ], ]; /** * Filters schema for services to add additional items. * * @internal * * @param array $schema Schema. */ $services_schema = apply_filters( 'amp_rest_options_schema', [] ); if ( ! is_array( $services_schema ) ) { $services_schema = []; } $this->schema['properties'] = array_merge( $this->schema['properties'], $services_schema ); } return $this->schema; } }