resolver = $resolver; } /** * Initialize REST API hooks. * * @since 1.0.0 * * @return void */ public function init(): void { add_action( 'rest_api_init', array( $this, 'register_routes' ) ); } /** * Register REST API routes. * * @since 1.0.0 * * @return void */ public function register_routes(): void { // Resolve endpoint: force re-resolve a post's fallback image. register_rest_route( self::NAMESPACE, '/resolve/(?P[\d]+)', array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'handle_resolve' ), 'permission_callback' => array( $this, 'check_permission' ), 'args' => array( 'post_id' => array( 'required' => true, 'validate_callback' => function ( $value ) { return is_numeric( $value ) && (int) $value > 0; }, 'sanitize_callback' => 'absint', 'description' => __( 'The post ID to resolve the fallback image for.', 'robotstxt-og' ), ), ), ) ); // Status endpoint: get current cached status for a post. register_rest_route( self::NAMESPACE, '/status/(?P[\d]+)', array( 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'handle_status' ), 'permission_callback' => array( $this, 'check_permission' ), 'args' => array( 'post_id' => array( 'required' => true, 'validate_callback' => function ( $value ) { return is_numeric( $value ) && (int) $value > 0; }, 'sanitize_callback' => 'absint', 'description' => __( 'The post ID to get the fallback image status for.', 'robotstxt-og' ), ), ), ) ); } /** * Handle the resolve endpoint. * * Forces re-resolution of the fallback image for the specified post. * * @since 1.0.0 * * @param WP_REST_Request $request REST request object. * @return WP_REST_Response|WP_Error Response object. */ public function handle_resolve( WP_REST_Request $request ) { $post_id = (int) $request->get_param( 'post_id' ); // Verify post exists. $post = get_post( $post_id ); if ( ! $post ) { return new WP_Error( 'post_not_found', __( 'Post not found.', 'robotstxt-og' ), array( 'status' => 404 ) ); } // Clear existing cache and resolve. $this->resolver->clear_cache( $post_id ); $resolved_url = $this->resolver->resolve_image( $post_id ); $data = array( 'post_id' => $post_id, 'resolved_url' => $resolved_url, 'cached' => ! empty( get_post_meta( $post_id, '_og_image_fallback_url', true ) ), 'success' => ! empty( $resolved_url ), ); return new WP_REST_Response( $data, 200 ); } /** * Handle the status endpoint. * * Returns the current cached fallback image status for a post. * * @since 1.0.0 * * @param WP_REST_Request $request REST request object. * @return WP_REST_Response|WP_Error Response object. */ public function handle_status( WP_REST_Request $request ) { $post_id = (int) $request->get_param( 'post_id' ); // Verify post exists. $post = get_post( $post_id ); if ( ! $post ) { return new WP_Error( 'post_not_found', __( 'Post not found.', 'robotstxt-og' ), array( 'status' => 404 ) ); } $cached_url = get_post_meta( $post_id, '_og_image_fallback_url', true ); $thumbnail_id = get_post_thumbnail_id( $post_id ); $original_url = $thumbnail_id ? wp_get_attachment_url( $thumbnail_id ) : ''; $data = array( 'post_id' => $post_id, 'cached_url' => $cached_url, 'original_url' => $original_url, 'has_cache' => ! empty( $cached_url ), ); return new WP_REST_Response( $data, 200 ); } /** * Check REST API permission. * * Requires manage_options capability. * * @since 1.0.0 * * @return bool|WP_Error True if authorized, WP_Error otherwise. */ public function check_permission() { if ( ! current_user_can( 'manage_options' ) ) { return new WP_Error( 'rest_forbidden', __( 'You do not have permission to access this endpoint.', 'robotstxt-og' ), array( 'status' => 403 ) ); } return true; } }