| @@ -1,14 +1,8 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | |
| 3 | 3 | namespace EmbedPress; |
| 4 | 4 | |
| 5 | -use EmbedPress\Includes\Classes\Helper; | |
| 6 | -use Embera\Embera; | |
| 7 | -use WP_Error as WP_ErrorAlias; | |
| 8 | -use WP_REST_Request; | |
| 9 | -use WP_REST_Response; | |
| 10 | - | |
| 11 | 5 | (defined('ABSPATH') && defined('EMBEDPRESS_IS_LOADED')) or die("No direct script access allowed."); |
| 12 | 6 | |
| 13 | 7 | /** |
| 14 | 8 | * Entity responsible for maintaining and registering all hooks that power the plugin. |
| @@ -14,182 +8,44 @@ | ||
| 14 | 8 | * Entity responsible for maintaining and registering all hooks that power the plugin. |
| 15 | 9 | * |
| 16 | 10 | * @package EmbedPress |
| 17 | 11 | * @author EmbedPress <help@embedpress.com> |
| 18 | - * @copyright Copyright (C) 2023 WPDeveloper. All rights reserved. | |
| 19 | - * @license GPLv3 or later | |
| 12 | + * @copyright Copyright (C) 2018 EmbedPress. All rights reserved. | |
| 13 | + * @license GPLv2 or later | |
| 20 | 14 | * @since 1.0.0 |
| 21 | 15 | */ |
| 22 | 16 | class RestAPI |
| 23 | 17 | { |
| 24 | 18 | /** |
| 25 | - * @param WP_REST_Request $request | |
| 26 | - * | |
| 27 | - * @return WP_REST_Response | WP_ErrorAlias | |
| 19 | + * @param \WP_REST_Request $request | |
| 28 | 20 | */ |
| 29 | 21 | public static function oembed($request) |
| 30 | 22 | { |
| 31 | - // Prevent infinite recursion: this endpoint IS the oembed provider, | |
| 32 | - // so if it triggers another oembed fetch that resolves back here, stop immediately. | |
| 33 | - static $is_processing = false; | |
| 34 | - if ($is_processing) { | |
| 35 | - return new WP_ErrorAlias( | |
| 36 | - 'embedpress_recursion', | |
| 37 | - 'Recursive oEmbed request detected', | |
| 38 | - ['status' => 508] | |
| 39 | - ); | |
| 40 | - } | |
| 41 | - $is_processing = true; | |
| 23 | + $url = sanitize_url($request->get_param('url')); | |
| 42 | 24 | |
| 43 | - $url = esc_url_raw($request->get_param('url')); | |
| 44 | - $playlist_id = $request->get_param( 'list'); | |
| 45 | - if ( !empty( $playlist_id) ) { | |
| 46 | - $url .= "&list=$playlist_id"; | |
| 47 | - } | |
| 48 | - | |
| 49 | - $atts = $request->get_params(); | |
| 50 | - | |
| 51 | - | |
| 52 | 25 | if (empty($url)) { |
| 53 | - $is_processing = false; | |
| 54 | - return new WP_ErrorAlias('embedpress_invalid_url', 'Invalid Embed URL', ['status' => 404]); | |
| 26 | + return new \WP_Error('embedpress_invalid_url', 'Invalid Embed URL', ['status' => 404]); | |
| 55 | 27 | } |
| 56 | 28 | |
| 57 | - // Validate URL has a proper scheme to reject malformed URLs early | |
| 58 | - if (!preg_match('#^https?://#i', $url)) { | |
| 59 | - $is_processing = false; | |
| 60 | - return new WP_ErrorAlias('embedpress_invalid_url', 'Invalid URL scheme', ['status' => 400]); | |
| 61 | - } | |
| 29 | + $config = []; | |
| 30 | + $embera = new \Embera\Embera($config); | |
| 62 | 31 | |
| 63 | - $atts = Helper::removeQuote($atts); | |
| 64 | - | |
| 65 | - // Map Meetup-specific Gutenberg attributes to shortcode attributes | |
| 66 | - if (!empty($url) && strpos($url, 'meetup.com') !== false) { | |
| 67 | - if (isset($atts['meetupOrderBy'])) { | |
| 68 | - $atts['orderby'] = $atts['meetupOrderBy']; | |
| 32 | + $additionalServiceProviders = Core::getAdditionalServiceProviders(); | |
| 33 | + if ( ! empty($additionalServiceProviders)) { | |
| 34 | + foreach ($additionalServiceProviders as $serviceProviderClassName => $serviceProviderUrls) { | |
| 35 | + Shortcode::addServiceProvider($serviceProviderClassName, $serviceProviderUrls, $embera); | |
| 69 | 36 | } |
| 70 | - if (isset($atts['meetupOrder'])) { | |
| 71 | - $atts['order'] = $atts['meetupOrder']; | |
| 72 | - } | |
| 73 | - if (isset($atts['meetupPerPage'])) { | |
| 74 | - $atts['per_page'] = $atts['meetupPerPage']; | |
| 75 | - } | |
| 76 | - if (isset($atts['meetupEnablePagination'])) { | |
| 77 | - $atts['enable_pagination'] = $atts['meetupEnablePagination']; | |
| 78 | - } | |
| 79 | - if (isset($atts['meetupTimezone'])) { | |
| 80 | - $atts['timezone'] = $atts['meetupTimezone']; | |
| 81 | - } | |
| 82 | - if (isset($atts['meetupDateFormat'])) { | |
| 83 | - $atts['date_format'] = $atts['meetupDateFormat']; | |
| 84 | - } | |
| 85 | - if (isset($atts['meetupTimeFormat'])) { | |
| 86 | - $atts['time_format'] = $atts['meetupTimeFormat']; | |
| 87 | - } | |
| 88 | 37 | } |
| 89 | 38 | |
| 90 | - $urlInfo = Shortcode::parseContent( $url, true, $atts); | |
| 91 | - $is_processing = false; | |
| 92 | - if (empty($urlInfo)) { | |
| 93 | - return new WP_ErrorAlias('embedpress_invalid_url', 'Invalid Embed URL', ['status' => 404]); | |
| 39 | + $urlInfo = $embera->getUrlInfo($url); | |
| 40 | + if (isset($urlInfo[$url])) { | |
| 41 | + $urlInfo = (object)$urlInfo[$url]; | |
| 42 | + $response['canBeResponsive'] = Core::canServiceProviderBeResponsive($urlInfo->provider_alias); | |
| 94 | 43 | } |
| 95 | - return new WP_REST_Response($urlInfo, 200); | |
| 96 | - } | |
| 97 | 44 | |
| 98 | - /** | |
| 99 | - * Lazy-load next page of YouTube playlist items for the queue layout. | |
| 100 | - * Returns rendered <li class="ep-yt-queue__item"> markup so the JS can | |
| 101 | - * just .insertAdjacentHTML — no client-side templating needed. | |
| 102 | - * | |
| 103 | - * GET /wp-json/embedpress/v1/youtube-playlist-items | |
| 104 | - * playlist_id PL… / RD… / UU… | |
| 105 | - * page_token YouTube pageToken from the prior response | |
| 106 | - * page_size items per request (1–50, default 6) | |
| 107 | - * offset starting index for the data-index attribute | |
| 108 | - */ | |
| 109 | - public static function youtube_playlist_items($request) | |
| 110 | - { | |
| 111 | - $playlist_id = (string) $request->get_param('playlist_id'); | |
| 112 | - $page_token = (string) $request->get_param('page_token'); | |
| 113 | - $page_size = (int) $request->get_param('page_size'); | |
| 114 | - $offset = (int) $request->get_param('offset'); | |
| 115 | - | |
| 116 | - if (empty($playlist_id) || empty($page_token)) { | |
| 117 | - return new WP_REST_Response(['html' => '', 'next_page_token' => ''], 200); | |
| 45 | + if (empty($urlInfo)) { | |
| 46 | + return new \WP_Error('embedpress_invalid_url', 'Invalid Embed URL', ['status' => 404]); | |
| 118 | 47 | } |
| 119 | - $page_size = $page_size > 0 && $page_size <= 50 ? $page_size : 6; | |
| 120 | 48 | |
| 121 | - $settings = (array) get_option(EMBEDPRESS_PLG_NAME . ':youtube', []); | |
| 122 | - $api_key = !empty($settings['api_key']) ? $settings['api_key'] : ''; | |
| 123 | - if (empty($api_key)) { | |
| 124 | - return new WP_REST_Response(['html' => '', 'next_page_token' => ''], 200); | |
| 125 | - } | |
| 126 | - | |
| 127 | - $endpoint = 'https://www.googleapis.com/youtube/v3/playlistItems?' . http_build_query([ | |
| 128 | - 'part' => 'snippet,status,contentDetails', | |
| 129 | - 'playlistId' => $playlist_id, | |
| 130 | - 'maxResults' => $page_size, | |
| 131 | - 'pageToken' => $page_token, | |
| 132 | - 'key' => $api_key, | |
| 133 | - ]); | |
| 134 | - | |
| 135 | - $transient_key = 'ep_yt_queue_page_' . md5($endpoint); | |
| 136 | - $json = get_transient($transient_key); | |
| 137 | - if (empty($json)) { | |
| 138 | - $resp = wp_remote_get($endpoint, ['timeout' => 30]); | |
| 139 | - if (is_wp_error($resp)) { | |
| 140 | - return new WP_REST_Response(['html' => '', 'next_page_token' => ''], 200); | |
| 141 | - } | |
| 142 | - $json = json_decode(wp_remote_retrieve_body($resp)); | |
| 143 | - if (empty($json) || !empty($json->error)) { | |
| 144 | - set_transient($transient_key, $json, 10); | |
| 145 | - return new WP_REST_Response(['html' => '', 'next_page_token' => ''], 200); | |
| 146 | - } | |
| 147 | - set_transient($transient_key, $json, MINUTE_IN_SECONDS * 20); | |
| 148 | - } | |
| 149 | - | |
| 150 | - $layout = (string) $request->get_param('layout'); | |
| 151 | - | |
| 152 | - // Pro layouts (library/spotlight/cinema/magazine) ship their own | |
| 153 | - // per-item markup, so let the Pro plugin filter the HTML when its | |
| 154 | - // layout is asked for. If no Pro filter is registered, we fall back | |
| 155 | - // to queue items below — matches the front-render fallback. | |
| 156 | - $pro_layouts = ['library', 'spotlight', 'cinema', 'magazine']; | |
| 157 | - if (in_array($layout, $pro_layouts, true)) { | |
| 158 | - $html = apply_filters( | |
| 159 | - 'embedpress/youtube_playlist_pro_items_html', | |
| 160 | - '', | |
| 161 | - $layout, | |
| 162 | - $json, | |
| 163 | - ['hideprivate' => false, 'thumbnail' => 'medium'], | |
| 164 | - $offset | |
| 165 | - ); | |
| 166 | - if ($html === '') { | |
| 167 | - $html = \EmbedPress\Providers\TemplateLayouts\YoutubeLayout::render_queue_items( | |
| 168 | - $json, | |
| 169 | - ['hideprivate' => false, 'thumbnail' => 'medium'], | |
| 170 | - $offset, | |
| 171 | - '' | |
| 172 | - ); | |
| 173 | - } | |
| 174 | - } elseif ($layout === 'theatre') { | |
| 175 | - $html = \EmbedPress\Providers\TemplateLayouts\YoutubeLayout::render_theatre_cards( | |
| 176 | - $json, | |
| 177 | - ['hideprivate' => false, 'thumbnail' => 'medium'], | |
| 178 | - $offset, | |
| 179 | - '' | |
| 180 | - ); | |
| 181 | - } else { | |
| 182 | - $html = \EmbedPress\Providers\TemplateLayouts\YoutubeLayout::render_queue_items( | |
| 183 | - $json, | |
| 184 | - ['hideprivate' => false, 'thumbnail' => 'medium'], | |
| 185 | - $offset, | |
| 186 | - '' | |
| 187 | - ); | |
| 188 | - } | |
| 189 | - | |
| 190 | - return new WP_REST_Response([ | |
| 191 | - 'html' => $html, | |
| 192 | - 'next_page_token' => isset($json->nextPageToken) ? $json->nextPageToken : '', | |
| 193 | - ], 200); | |
| 49 | + return new \WP_REST_Response($urlInfo, 202); | |
| 194 | 50 | } |
| 195 | 51 | } |