Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 85
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
WPCOM_JSON_API_Render_Embed_Reversal_Endpoint
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 2
420
0.00% covered (danger)
0.00%
0 / 1
 callback
0.00% covered (danger)
0.00%
0 / 46
0.00% covered (danger)
0.00%
0 / 1
306
 render_shortcode_reversal
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
1<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3if ( ! defined( 'ABSPATH' ) ) {
4    exit( 0 );
5}
6
7new WPCOM_JSON_API_Render_Embed_Reversal_Endpoint(
8    array(
9        'description'          => 'Determines if the given embed code can be reversed into a single line embed or a shortcode, and if so returns the embed or shortcode. Note: The current user must have publishing access.',
10        'group'                => '__do_not_document',
11        'stat'                 => 'embeds:reversal',
12        'method'               => 'POST',
13        'path'                 => '/sites/%s/embeds/reversal',
14        'path_labels'          => array(
15            '$site' => '(int|string) Site ID or domain',
16        ),
17        'request_format'       => array(
18            'maybe_embed' => '(string) The embed code to reverse. Required. Only accepts one at a time.',
19        ),
20        'response_format'      => array(
21            'maybe_embed'   => '(string) The original embed code that was passed in for rendering.',
22            'reversal_type' => '(string) The type of reversal. Either an embed or a shortcode.',
23            'render_result' => '(html) The rendered HTML result of the embed or shortcode.',
24            'result'        => '(string) The reversed content. Either a single line embed or a shortcode.',
25            'scripts'       => '(array) An array of JavaScript files needed to render the embed or shortcode. Returned in the format of <code>{ "script-slug" : { "src": "http://example.com/file.js", "extra" : "" } }</code> where extra contains any neccessary extra JS for initializing the source file and src contains the script to load. Omitted if no scripts are neccessary.',
26            'styles'        => '(array) An array of CSS files needed to render the embed or shortcode. Returned in the format of <code>{ "style-slug" : { "src": "http://example.com/file.css", "media" : "all" } }</code>. Omitted if no styles are neccessary.',
27        ),
28        'example_request'      => 'https://public-api.wordpress.com/rest/v1/sites/82974409/shortcode-reversals/render/',
29        'example_request_data' => array(
30            'headers' => array(
31                'authorization' => 'Bearer YOUR_API_TOKEN',
32            ),
33
34            'body'    => array(
35                'maybe_embed' => '<iframe width="480" height="302" src="http://www.ustream.tv/embed/recorded/26370522/highlight/299667?v=3&amp;wmode=direct" scrolling="no" frameborder="0"></iframe>',
36            ),
37        ),
38    )
39);
40
41/**
42 * Render embed reversal class.
43 *
44 * /sites/%s/embeds/reversal -> $blog_id
45 *
46 * @phan-constructor-used-for-side-effects
47 */
48class WPCOM_JSON_API_Render_Embed_Reversal_Endpoint extends WPCOM_JSON_API_Render_Endpoint {
49    /**
50     * API callback.
51     *
52     * @param string $path - the path (unused).
53     * @param int    $blog_id - the blog ID.
54     *
55     * @return array|WP_Error
56     */
57    public function callback( $path = '', $blog_id = 0 ) {
58        $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
59        if ( is_wp_error( $blog_id ) ) {
60            return $blog_id;
61        }
62
63        if ( ! current_user_can( 'edit_posts' ) ) {
64            return new WP_Error( 'unauthorized', 'Your token must have permission to post on this blog.', 403 );
65        }
66
67        $is_embed     = false;
68        $is_shortcode = false;
69
70        $input       = $this->input( true );
71        $maybe_embed = trim( $input['maybe_embed'] );
72        if ( empty( $maybe_embed ) ) {
73            return new WP_Error( 'empty_embed', 'Please provide an embed code to process.', 400 );
74        }
75
76        $ksesed_content = trim( wp_strip_all_tags( wp_kses_post( $maybe_embed ), true ) );
77        if ( empty( $ksesed_content ) ) {
78            return new WP_Error( 'invalid_embed', 'Invalid or empty embed provided.', 400 );
79        }
80
81        $shortcode_pattern = get_shortcode_regex();
82        $url_pattern       = '/^http(s)?:\/\/[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(\/.*)?$/i';
83        preg_match_all( "/$shortcode_pattern/s", $ksesed_content, $shortcode_matches );
84        preg_match_all( "$url_pattern", $ksesed_content, $url_matches );
85
86        if ( empty( $shortcode_matches[0] ) && empty( $url_matches[0] ) ) {
87            return new WP_Error( 'invalid_embed', 'The provided embed is not supported.', 400 );
88        }
89
90        $shortcode_matches_count = is_countable( $shortcode_matches[0] ) ? count( $shortcode_matches[0] ) : 0;
91        $url_matches_count       = is_countable( $url_matches[0] ) ? count( $url_matches[0] ) : 0;
92        if ( ( $shortcode_matches_count + $url_matches_count ) > 1 ) {
93            return new WP_Error( 'invalid_embed', 'Only one embed/shortcode reversal can be rendered at a time.', 400 );
94        }
95
96        if ( ! empty( $shortcode_matches[0] ) ) {
97            $is_shortcode = true;
98        } elseif ( ! empty( $url_matches[0] ) ) {
99            $is_embed = true;
100        }
101
102        $render = $this->process_render(
103            array( $this, 'render_shortcode_reversal' ),
104            array(
105                'shortcode_reversal' => $ksesed_content,
106                'is_shortcode'       => $is_shortcode,
107                'is_embed'           => $is_embed,
108            )
109        );
110
111        // if nothing happened, then the shortcode does not exist.
112        global $wp_embed;
113        if ( empty( $render ) || empty( $render['result'] ) || $ksesed_content === $render['result'] || $wp_embed->maybe_make_link( $maybe_embed ) === $render['result'] ) {
114            return new WP_Error( 'invalid_embed', 'The provided embed is not supported.', 400 );
115        }
116
117        // our output for this endpoint..
118        $return                  = array();
119        $return['maybe_embed']   = $maybe_embed;
120        $return['result']        = $ksesed_content;
121        $return['reversal_type'] = ( $is_embed ) ? 'embed' : 'shortcode';
122        $return['render_result'] = $render['result'];
123
124        $return = $this->add_assets( $return, $render['loaded_scripts'], $render['loaded_styles'] );
125
126        return $return;
127    }
128
129    /**
130     * Render the shortcode reversal.
131     *
132     * @param array $args - the arguments.
133     *
134     * @return mixed|false
135     */
136    public function render_shortcode_reversal( $args ) {
137        if ( $args['is_shortcode'] ) {
138            return $this->do_shortcode( $args['shortcode_reversal'] );
139        } elseif ( $args['is_embed'] ) {
140            return $this->do_embed( $args['shortcode_reversal'] );
141        }
142        return false;
143    }
144}