Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
82.14% covered (warning)
82.14%
23 / 28
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
WPCOM_REST_API_V2_Verbum_OEmbed
85.19% covered (warning)
85.19%
23 / 27
75.00% covered (warning)
75.00%
3 / 4
6.12
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 register_routes
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
 permission_callback
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 get_embed_data
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2/**
3 * Plugin Name: Verbum Comments Experience Embeds.
4 * Description: This is used to get the embed data for the embed block. The core API requires authentication, so we need to create our own endpoint.
5 * Author: Vertex
6 * Text Domain: jetpack-mu-wpcom
7 *
8 * @package automattic/jetpack-mu-plugins
9 */
10
11declare( strict_types = 1 );
12
13/**
14 * Verbum Comments Experience Embeds endpoint.
15 */
16class WPCOM_REST_API_V2_Verbum_OEmbed extends \WP_REST_Controller {
17    /**
18     * Constructor.
19     */
20    public function __construct() {
21        $this->namespace                       = 'wpcom/v2';
22        $this->rest_base                       = '/verbum/embed';
23        $this->wpcom_is_wpcom_only_endpoint    = false;
24        $this->wpcom_is_site_specific_endpoint = false;
25        add_action( 'rest_api_init', array( $this, 'register_routes' ) );
26    }
27
28    /**
29     * Register the routes for the objects of the controller.
30     */
31    public function register_routes() {
32        register_rest_route(
33            $this->namespace,
34            $this->rest_base,
35            array(
36                'show_in_index'       => false,
37                'methods'             => \WP_REST_Server::READABLE,
38                'callback'            => array( $this, 'get_embed_data' ),
39                'permission_callback' => array( $this, 'permission_callback' ),
40            )
41        );
42    }
43
44    /**
45     * Check if the user is authenticated.
46     *
47     * @param WP_REST_Request $request The request object.
48     * @return bool
49     */
50    public function permission_callback( WP_REST_Request $request ) {
51        if ( is_user_logged_in() ) {
52            return true; // Bypass nonce check for logged-in users.
53        }
54
55        $nonce = $request->get_param( 'embed_nonce' );
56
57        return wp_verify_nonce( $nonce, 'embed_nonce' );
58    }
59
60    /**
61     * Get the embed data for the embed block.
62     *
63     * @param WP_REST_Request $request The request object.
64     * @return object|\WP_Error
65     */
66    public function get_embed_data( WP_REST_Request $request ) {
67        $url      = sanitize_url( $request->get_param( 'embed_url' ) );
68        $instance = new WP_oEmbed();
69        // Skip discovery so only listed providers resolve, as with comment embeds on the front end.
70        $args       = array( 'discover' => false );
71        $embed_data = $instance->get_data( $url, $args );
72
73        // Return error if the embed data is empty.
74        // This matches the core response.
75        if ( false === $embed_data ) {
76            return new \WP_Error( 'oembed_invalid_url', get_status_header_desc( 404 ), array( 'status' => 404 ) );
77        }
78
79        // Build the HTML like the core oEmbed proxy.
80        /** This filter is documented in wp-includes/class-wp-oembed.php */
81        $embed_data->html = apply_filters( 'oembed_result', $instance->data2html( $embed_data, $url ), $url, $args );
82
83        return $embed_data;
84    }
85}
86
87wpcom_rest_api_v2_load_plugin( 'WPCOM_REST_API_V2_Verbum_oEmbed' );