base_api_path = 'wpcom'; $this->version = 'v2'; $this->namespace = "{$this->base_api_path}/{$this->version}"; $this->rest_base = 'publicize/share-post'; add_action( 'rest_api_init', array( $this, 'register_routes' ) ); } /** * Register the routes. */ public function register_routes() { $args = array( 'methods' => WP_REST_Server::CREATABLE, 'callback' => array( $this, 'share_post' ), 'permission_callback' => array( $this, 'permissions_check' ), 'args' => array( 'message' => array( 'description' => __( 'The message to share.', 'jetpack-publicize-pkg' ), 'type' => 'string', 'required' => true, 'validate_callback' => function ( $param ) { return is_string( $param ); }, 'sanitize_callback' => 'sanitize_textarea_field', ), 'skipped_connections' => array( 'description' => __( 'Array of external connection IDs to skip sharing.', 'jetpack-publicize-pkg' ), 'type' => 'array', 'required' => false, 'validate_callback' => function ( $param ) { return is_array( $param ); }, 'sanitize_callback' => function ( $param ) { if ( ! is_array( $param ) ) { return new WP_Error( 'rest_invalid_param', esc_html__( 'The skipped_connections argument must be an array of connection IDs.', 'jetpack-publicize-pkg' ), array( 'status' => 400 ) ); } return array_map( 'absint', $param ); }, ), 'async' => array( 'description' => __( 'Whether to share the post asynchronously.', 'jetpack-publicize-pkg' ), 'type' => 'boolean', 'default' => false, ), ), ); register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P\d+)', $args ); if ( Utils::is_wpcom() ) { // WPCOM Legacy route for backwards compatibility. // TODO: Remove this after April 2025 release of Jetpack. register_rest_route( $this->namespace, '/posts/(?P\d+)/publicize', $args ); } } /** * Ensure the user has proper tokens and permissions to publish posts on this blog. * * @return WP_Error|boolean */ public function permissions_check() { return $this->publicize_permissions_check(); } /** * If this method callback is executed on WPCOM, we share the post using republicize_post(). If this method callback * is executed on a Jetpack site, we make an API call to WPCOM using wpcom_json_api_request_as_user() and return * the results. In both cases, this file and method are executed, as this file is synced from Jetpack to WPCOM. * * @param WP_REST_Request $request Full details about the request. * @return WP_REST_Response|WP_Error The publicize results, including two arrays: `results` and `errors` */ public function share_post( $request ) { $post_id = $request->get_param( 'postId' ); if ( ! Utils::is_wpcom() ) { return rest_ensure_response( $this->proxy_request_to_wpcom_as_user( $request, $post_id ) ); } $message = trim( $request->get_param( 'message' ) ); $skip_connection_ids = $request->get_param( 'skipped_connections' ); $async = (bool) $request->get_param( 'async' ); $post = get_post( $post_id ); if ( empty( $post ) ) { return new WP_Error( 'not_found', __( 'Cannot find that post.', 'jetpack-publicize-pkg' ), array( 'status' => 404 ) ); } if ( 'publish' !== $post->post_status ) { return new WP_Error( 'not_published', __( 'Only published posts can be shared.', 'jetpack-publicize-pkg' ), array( 'status' => 400 ) ); } global $publicize; // @phan-suppress-next-line PhanUndeclaredMethod - We are on WPCOM where republicize_post is available. $result = $publicize->republicize_post( (int) $post_id, $message, $skip_connection_ids, true, ! $async, get_current_user_id() ); if ( false === $result ) { return new WP_Error( 'not_found', __( 'Cannot find that post.', 'jetpack-publicize-pkg' ), array( 'status' => 404 ) ); } return rest_ensure_response( $result ); } }