\d+)/translations', array( array( 'methods' => WP_REST_Server::READABLE, 'callback' => $this->safely( array( $this, 'index' ) ), 'permission_callback' => $can_edit, 'args' => self::id_arg(), ), array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => $this->safely( array( $this, 'create' ) ), 'permission_callback' => array( $this, 'can_create' ), 'args' => array_merge( self::id_arg(), array( 'lang' => array( 'type' => 'string', 'required' => true, ), 'mode' => array( 'type' => 'string', 'enum' => array( Duplicator::MODE_COPY, Duplicator::MODE_MACHINE, Duplicator::MODE_EMPTY ), 'default' => Duplicator::MODE_COPY, ), 'title' => array( 'type' => 'string' ), 'content' => array( 'type' => 'string' ), 'excerpt' => array( 'type' => 'string' ), 'translate_meta' => array( 'type' => 'boolean', 'default' => false, ), ) ), ), ) ); register_rest_route( self::NS, '/post/(?P\d+)/unlink', array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => $this->safely( array( $this, 'unlink' ) ), 'permission_callback' => $can_edit, 'args' => self::id_arg(), ) ); register_rest_route( self::NS, '/post/(?P\d+)/raw', array( 'methods' => WP_REST_Server::READABLE, 'callback' => $this->safely( array( $this, 'raw' ) ), 'permission_callback' => $can_edit, 'args' => self::id_arg(), ) ); } /** * Edit the source post; machine mode and translated SEO fields also spend the API key. * * @param WP_REST_Request> $request */ public function can_create( WP_REST_Request $request ): bool { if ( ! $this->can_edit_post( $request ) ) { return false; } $machine = Duplicator::MODE_MACHINE === $request['mode'] || ! empty( $request['translate_meta'] ); return ! $machine || self::can_machine_translate(); } /** @param WP_REST_Request> $request */ public function index( WP_REST_Request $request ): WP_REST_Response { $id = (int) $request['id']; $out = array(); foreach ( $this->posts->group( $id ) as $lang => $post_id ) { if ( $post_id === $id ) { continue; } $described = self::describe( $post_id ); if ( $described ) { $out[ $lang ] = $described; } } return new WP_REST_Response( array( 'lang' => $this->posts->language_of( $id ), 'translations' => (object) $out, ) ); } /** @param WP_REST_Request> $request */ public function create( WP_REST_Request $request ): WP_REST_Response|WP_Error { $id = (int) $request['id']; $post = get_post( $id ); if ( ! $post || ! $this->settings->get()->is_translatable_type( $post->post_type ) ) { return new WP_Error( 'blocklingo_not_translatable', __( 'This post type is not translatable.', 'blocklingo' ), array( 'status' => 400 ) ); } $type = get_post_type_object( $post->post_type ); if ( ! $type || ! current_user_can( $type->cap->create_posts ) ) { return new WP_Error( 'blocklingo_forbidden', __( 'You cannot create posts of this type.', 'blocklingo' ), array( 'status' => 403 ) ); } $overrides = array(); foreach ( array( 'title', 'content', 'excerpt' ) as $field ) { if ( null !== $request[ $field ] ) { $overrides[ $field ] = (string) $request[ $field ]; } } $new_id = $this->duplicator->create( $id, (string) $request['lang'], (string) $request['mode'], $overrides, (bool) $request['translate_meta'] ); if ( $new_id instanceof WP_Error ) { return self::fail( $new_id, 400 ); } return new WP_REST_Response( self::describe( $new_id ) ); } /** @param WP_REST_Request> $request */ public function unlink( WP_REST_Request $request ): WP_REST_Response|WP_Error { $result = $this->translations->unlink( (int) $request['id'] ); return $result instanceof WP_Error ? $result : new WP_REST_Response( array( 'ok' => true ) ); } /** @param WP_REST_Request> $request */ public function raw( WP_REST_Request $request ): WP_REST_Response|WP_Error { $post = get_post( (int) $request['id'] ); if ( ! $post ) { return new WP_Error( 'blocklingo_no_post', __( 'Post not found.', 'blocklingo' ), array( 'status' => 404 ) ); } return new WP_REST_Response( array( 'id' => $post->ID, 'lang' => $this->posts->language_of( $post->ID ), 'title' => $post->post_title, 'content' => $post->post_content, 'excerpt' => $post->post_excerpt, ) ); } /** @return array{id: int, title: string, status: string, edit_link: string|null, view_link: string|false}|null */ private static function describe( int $post_id ): ?array { $post = get_post( $post_id ); if ( ! $post ) { return null; } return array( 'id' => $post->ID, 'title' => get_the_title( $post ), 'status' => $post->post_status, 'edit_link' => get_edit_post_link( $post->ID, 'raw' ), 'view_link' => get_permalink( $post ), ); } }