Yoast\WP\SEO\AI\Content_Planner\User_Interface

Get_Outline_Route{}Yoast 1.0└─ Route_Interface

Registers a route to get a content outline from the AI API.

Хуков нет.

Использование

$Get_Outline_Route = new Get_Outline_Route();
// use class methods

Методы

  1. public __construct( Content_Outline_Command_Handler $command_handler )
  2. public check_permissions( WP_REST_Request $request )
  3. public static get_conditionals()
  4. public get_outline( WP_REST_Request $request )
  5. public register_routes()

Код Get_Outline_Route{} Yoast 28.3

class Get_Outline_Route implements Route_Interface {

	/**
	 * The namespace for this route.
	 *
	 * @var string
	 */
	public const ROUTE_NAMESPACE = Main::API_V1_NAMESPACE;

	/**
	 * The prefix for this route.
	 *
	 * @var string
	 */
	public const ROUTE_PREFIX = '/ai_content_planner/get_outline';

	/**
	 * The command handler instance.
	 *
	 * @var Content_Outline_Command_Handler
	 */
	private $command_handler;

	/**
	 * Returns the conditionals based in which this loadable should be active.
	 *
	 * @return array<string> The conditionals.
	 */
	public static function get_conditionals() {
		return [ AI_Conditional::class ];
	}

	/**
	 * Class constructor.
	 *
	 * @param Content_Outline_Command_Handler $command_handler The command handler instance.
	 */
	public function __construct( Content_Outline_Command_Handler $command_handler ) {
		$this->command_handler = $command_handler;
	}

	/**
	 * Registers routes with WordPress.
	 *
	 * @return void
	 */
	public function register_routes() {
		\register_rest_route(
			self::ROUTE_NAMESPACE,
			self::ROUTE_PREFIX,
			[
				'methods'             => 'POST',
				'args'                => [
					'post_type'        => [
						'required'    => true,
						'type'        => 'string',
						'description' => 'The post type to get a content outline for.',
					],
					'language'         => [
						'required'    => true,
						'type'        => 'string',
						'description' => 'The language the content is written in.',
					],
					'editor'           => [
						'required'    => true,
						'type'        => 'string',
						'enum'        => [
							'classic',
							'elementor',
							'gutenberg',
						],
						'description' => 'The current editor.',
					],
					'title'            => [
						'required'    => true,
						'type'        => 'string',
						'description' => 'The title of the chosen content suggestion.',
					],
					'intent'           => [
						'required'    => true,
						'type'        => 'string',
						'description' => 'The intent of the chosen content suggestion.',
					],
					'explanation'      => [
						'required'    => true,
						'type'        => 'string',
						'description' => 'The explanation of the chosen content suggestion.',
					],
					'keyphrase'        => [
						'required'    => true,
						'type'        => 'string',
						'description' => 'The keyphrase of the chosen content suggestion.',
					],
					'meta_description' => [
						'required'    => true,
						'type'        => 'string',
						'description' => 'The meta description of the chosen content suggestion.',
					],
					'category'         => [
						'required'    => true,
						'type'        => 'object',
						'properties'  => [
							'name' => [
								'type'     => 'string',
								'required' => true,
							],
							'id'   => [
								'type'     => 'integer',
								'required' => true,
							],
						],
						'description' => 'The category of the chosen content suggestion. Use name "" and id -1 to indicate no category.',
					],
					'recent_content'   => [
						'required'    => true,
						'type'        => 'array',
						'maxItems'    => 100,
						'items'       => [
							'type'                 => 'object',
							'properties'           => [
								'title'       => [
									'type'      => 'string',
									'required'  => true,
									'maxLength' => 500,
								],
								'description' => [
									'type'      => 'string',
									'required'  => true,
									'maxLength' => 1000,
								],
							],
							'additionalProperties' => false,
						],
						'description' => 'The recent content returned by the get_suggestions response.',
					],
				],
				'callback'            => [ $this, 'get_outline' ],
				'permission_callback' => [ $this, 'check_permissions' ],
			],
		);
	}

	/**
	 * Runs the callback to get an AI-generated content outline.
	 *
	 * @param WP_REST_Request $request The request object.
	 *
	 * @return WP_REST_Response The response of the get_outline action.
	 */
	public function get_outline( WP_REST_Request $request ): WP_REST_Response {
		try {
			$user = \wp_get_current_user();

			$category_param = $request->get_param( 'category' );

			$command = new Content_Outline_Command(
				$user,
				$request->get_param( 'post_type' ),
				$request->get_param( 'language' ),
				$request->get_param( 'editor' ),
				$request->get_param( 'title' ),
				$request->get_param( 'intent' ),
				$request->get_param( 'explanation' ),
				$request->get_param( 'keyphrase' ),
				$request->get_param( 'meta_description' ),
				$category_param['name'],
				(int) $category_param['id'],
				$request->get_param( 'recent_content' ),
			);
			$data    = $this->command_handler->handle( $command );
		} catch ( Remote_Request_Exception $e ) {
			$message = [
				'message'         => $e->getMessage(),
				'errorIdentifier' => $e->get_error_identifier(),
			];
			if ( $e instanceof Payment_Required_Exception || $e instanceof Too_Many_Requests_Exception ) {
				$message['missingLicenses'] = $e->get_missing_licenses();
			}
			return new WP_REST_Response(
				$message,
				$e->getCode(),
			);
		} catch ( RuntimeException $e ) {
			return new WP_REST_Response( 'Failed to get content outline.', 500 );
		}

		return new WP_REST_Response( $data->to_array() );
	}

	/**
	 * Checks if the user is logged in and can edit posts of the requested post type.
	 *
	 * The requested post_type is caller-controlled, so the permission must be evaluated
	 * against that post type's own edit_posts meta-capability — not the generic
	 * 'edit_posts' string, which would let a user with edit_posts but no edit_pages
	 * (e.g. an Author) trigger outline generation for pages or arbitrary CPTs.
	 *
	 * @param WP_REST_Request $request The request object.
	 *
	 * @return bool Whether the user can edit posts of the requested post type.
	 */
	public function check_permissions( WP_REST_Request $request ): bool {
		$user = \wp_get_current_user();
		if ( $user === null || $user->ID < 1 ) {
			return false;
		}

		$post_type        = $request->get_param( 'post_type' );
		$post_type_object = \get_post_type_object( $post_type );
		if ( $post_type_object === null ) {
			return false;
		}

		return \user_can( $user, $post_type_object->cap->edit_posts );
	}
}