| @@ -30,30 +30,22 @@ | ||
| 30 | 30 | */ |
| 31 | 31 | protected $api_key; |
| 32 | 32 | |
| 33 | 33 | /** |
| 34 | - * Array of query params. | |
| 34 | + * The YouTube API URLs. | |
| 35 | 35 | * |
| 36 | - * @since 2.5.7 | |
| 36 | + * @since 1.0.0 | |
| 37 | 37 | * @access protected |
| 38 | 38 | * @var array |
| 39 | 39 | */ |
| 40 | - protected $params = array(); | |
| 40 | + public $api_urls = array( | |
| 41 | + 'playlistItems.list' => 'https://www.googleapis.com/youtube/v3/playlistItems', | |
| 42 | + 'channels.list' => 'https://www.googleapis.com/youtube/v3/channels', | |
| 43 | + 'search.list' => 'https://www.googleapis.com/youtube/v3/search', | |
| 44 | + 'videos.list' => 'https://www.googleapis.com/youtube/v3/videos' | |
| 45 | + ); | |
| 41 | 46 | |
| 42 | 47 | /** |
| 43 | - * May this query write gallery membership rows? | |
| 44 | - * | |
| 45 | - * Opt-in, set from the "store" query param. Only trusted server side callers set it — the | |
| 46 | - * page renderer (ayg_build_gallery), the Gallery Builder importer, and the public AJAX | |
| 47 | - * endpoint once it has resolved the gallery itself. See request_api(). | |
| 48 | - * | |
| 49 | - * @since 2.9.0 | |
| 50 | - * @access protected | |
| 51 | - * @var bool | |
| 52 | - */ | |
| 53 | - protected $can_store = false; | |
| 54 | - | |
| 55 | - /** | |
| 56 | 48 | * Is development mode enabled? |
| 57 | 49 | * |
| 58 | 50 | * @since 2.3.0 |
| 59 | 51 | * @access protected |
| @@ -61,54 +53,23 @@ | ||
| 61 | 53 | */ |
| 62 | 54 | protected $is_development_mode = false; |
| 63 | 55 | |
| 64 | 56 | /** |
| 65 | - * The YouTube API URLs. | |
| 57 | + * Get videos. | |
| 66 | 58 | * |
| 67 | 59 | * @since 1.0.0 |
| 68 | - * @access protected | |
| 69 | - * @var array | |
| 70 | - */ | |
| 71 | - public $api_urls = array( | |
| 72 | - 'playlistItems.list' => 'https://www.googleapis.com/youtube/v3/playlistItems', | |
| 73 | - 'channels.list' => 'https://www.googleapis.com/youtube/v3/channels', | |
| 74 | - 'search.list' => 'https://www.googleapis.com/youtube/v3/search', | |
| 75 | - 'videos.list' => 'https://www.googleapis.com/youtube/v3/videos' | |
| 76 | - ); | |
| 77 | - | |
| 78 | - /** | |
| 79 | - * Get videos. | |
| 80 | - * | |
| 81 | - * Side effect: successful responses are persisted to the custom tables via | |
| 82 | - * ayg_db_store_videos() (called inside request_api()) — video rows always, and | |
| 83 | - * gallery relationships only when the caller passes both a "uid" and "store" => true. | |
| 84 | - * This is how both legacy galleries and the Gallery Builder importer store their videos. | |
| 85 | - * | |
| 86 | - * "store" must never be set from user input: it decides which gallery the fetched videos | |
| 87 | - * are shown in. Callers reachable by unauthenticated visitors have to resolve the gallery | |
| 88 | - * server side first — see AYG_Public::ajax_callback_load_videos(). | |
| 89 | - * | |
| 90 | - * @since 1.0.0 | |
| 91 | - * @param array $params Array of query params. | |
| 60 | + * @param array $params Array of query params. | |
| 92 | 61 | * @return mixed |
| 93 | 62 | */ |
| 94 | 63 | public function query( $params = array() ) { |
| 95 | 64 | // Get YouTube API Key |
| 96 | - $general_settings = ayg_get_option( 'ayg_general_settings' ); | |
| 65 | + $general_settings = get_option( 'ayg_general_settings' ); | |
| 97 | 66 | |
| 98 | - // DB-served responses (gallery search + the internal "db" source type) read from the | |
| 99 | - // custom tables, so they're handled before the API-key guard — no key required. | |
| 100 | - if ( ! empty( $params['searchTerm'] ) || ( isset( $params['type'] ) && 'db' === $params['type'] ) ) { | |
| 101 | - return $this->get_videos_from_db( $params ); | |
| 102 | - } | |
| 103 | - | |
| 104 | 67 | if ( empty( $general_settings['api_key'] ) ) { |
| 105 | - return $this->get_error( __( 'YouTube API key not found.', 'automatic-youtube-gallery' ) . ' ' . sprintf( __( 'Kindly follow this URL <a href="%s" target="_blank" rel="noopener noreferrer">this guide</a> to get your own API key.', 'automatic-youtube-gallery' ), 'https://plugins360.com/automatic-youtube-gallery/how-to-get-youtube-api-key/' ) ); | |
| 68 | + return $this->get_error( __( 'YouTube API key not found.', 'automatic-youtube-gallery' ) . ' ' . sprintf( __( 'Kindly follow this URL <a href="%s" target="_blank">this guide</a> to get your own API key.', 'automatic-youtube-gallery' ), 'https://plugins360.com/automatic-youtube-gallery/how-to-get-youtube-api-key/' ) ); | |
| 106 | 69 | } |
| 107 | 70 | |
| 108 | - $this->api_key = $general_settings['api_key']; | |
| 109 | - $this->params = $params; | |
| 110 | - $this->can_store = ! empty( $params['store'] ); | |
| 71 | + $this->api_key = $general_settings['api_key']; | |
| 111 | 72 | |
| 112 | 73 | // Is development mode enabled? |
| 113 | 74 | if ( isset( $general_settings['development_mode'] ) && ! empty( $general_settings['development_mode'] ) ) { |
| 114 | 75 | $this->is_development_mode = true; |
| @@ -113,13 +74,8 @@ | ||
| 113 | 74 | if ( isset( $general_settings['development_mode'] ) && ! empty( $general_settings['development_mode'] ) ) { |
| 114 | 75 | $this->is_development_mode = true; |
| 115 | 76 | } |
| 116 | 77 | |
| 117 | - // Advanced mode fetches duration + live broadcast details via a supplementary | |
| 118 | - // videos.list call (used by the Gallery Builder importer). Defaults to off so | |
| 119 | - // legacy galleries make no extra API request. | |
| 120 | - $mode = isset( $params['mode'] ) ? $params['mode'] : 'basic'; | |
| 121 | - | |
| 122 | 78 | // Process output |
| 123 | 79 | $response = array(); |
| 124 | 80 | |
| 125 | 81 | switch ( $params['type'] ) { |
| @@ -124,9 +80,9 @@ | ||
| 124 | 80 | |
| 125 | 81 | switch ( $params['type'] ) { |
| 126 | 82 | case 'playlist': |
| 127 | 83 | if ( empty( $params['src'] ) ) { |
| 128 | - return $this->get_error( __( 'A YouTube playlist ID (or) URL is required.', 'automatic-youtube-gallery' ) ); | |
| 84 | + return $this->get_error( __( 'YouTube Playlist ID (or) URL is required.', 'automatic-youtube-gallery' ) ); | |
| 129 | 85 | } |
| 130 | 86 | |
| 131 | 87 | $response = $this->request_api_playlist_items( $params ); |
| 132 | 88 | break; |
| @@ -132,21 +88,15 @@ | ||
| 132 | 88 | break; |
| 133 | 89 | |
| 134 | 90 | case 'channel': |
| 135 | 91 | if ( empty( $params['src'] ) ) { |
| 136 | - return $this->get_error( __( 'A YouTube channel ID (or) a video URL from the channel is required.', 'automatic-youtube-gallery' ) ); | |
| 92 | + return $this->get_error( __( 'YouTube Channel ID (or) or a YouTube Video URL from the Channel is required.', 'automatic-youtube-gallery' ) ); | |
| 137 | 93 | } |
| 138 | 94 | |
| 139 | - // @handle URLs can't be resolved to a channel ID here (mirrors the client-side | |
| 140 | - // check in admin.js / gallery-form.php). | |
| 141 | - if ( false !== strpos( $params['src'], '@' ) ) { | |
| 142 | - return $this->get_error( __( 'YouTube @handle URLs aren’t supported here. Please enter a channel ID, a /channel/ URL, or a video URL from the channel.', 'automatic-youtube-gallery' ) ); | |
| 143 | - } | |
| 144 | - | |
| 145 | 95 | $params['id'] = $this->get_channel_id( $params ); |
| 146 | 96 | |
| 147 | 97 | if ( empty( $params['id'] ) ) { |
| 148 | - return $this->get_error( __( 'Invalid YouTube channel ID.', 'automatic-youtube-gallery' ) ); | |
| 98 | + return $this->get_error( __( 'Invalid YouTube Channel ID.', 'automatic-youtube-gallery' ) ); | |
| 149 | 99 | } |
| 150 | 100 | |
| 151 | 101 | // Get playlist id from the channel |
| 152 | 102 | $playlist_id = $this->get_playlist_id( $params ); |
| @@ -165,9 +115,9 @@ | ||
| 165 | 115 | break; |
| 166 | 116 | |
| 167 | 117 | case 'username': |
| 168 | 118 | if ( empty( $params['src'] ) ) { |
| 169 | - return $this->get_error( __( 'A YouTube account username is required.', 'automatic-youtube-gallery' ) ); | |
| 119 | + return $this->get_error( __( 'YouTube Account Username is required.', 'automatic-youtube-gallery' ) ); | |
| 170 | 120 | } |
| 171 | 121 | |
| 172 | 122 | // Get playlist id from the channel |
| 173 | 123 | $params['forUsername'] = $this->parse_youtube_id_from_url( $params['src'], 'username' ); |
| @@ -187,9 +137,9 @@ | ||
| 187 | 137 | break; |
| 188 | 138 | |
| 189 | 139 | case 'search': |
| 190 | 140 | if ( empty( $params['src'] ) ) { |
| 191 | - return $this->get_error( __( 'A search keyword is required.', 'automatic-youtube-gallery' ) ); | |
| 141 | + return $this->get_error( __( 'Cannot search an empty string. A search keyword is required.', 'automatic-youtube-gallery' ) ); | |
| 192 | 142 | } |
| 193 | 143 | |
| 194 | 144 | $response = $this->request_api_search( $params ); |
| 195 | 145 | break; |
| @@ -195,9 +145,9 @@ | ||
| 195 | 145 | break; |
| 196 | 146 | |
| 197 | 147 | case 'videos': |
| 198 | 148 | if ( empty( $params['src'] ) ) { |
| 199 | - return $this->get_error( __( 'At least one YouTube video ID (or) URL is required.', 'automatic-youtube-gallery' ) ); | |
| 149 | + return $this->get_error( __( 'Atleast one YouTube Video ID (or) URL is required.', 'automatic-youtube-gallery' ) ); | |
| 200 | 150 | } |
| 201 | 151 | |
| 202 | 152 | $response = $this->request_api_videos( $params ); |
| 203 | 153 | break; |
| @@ -203,21 +153,15 @@ | ||
| 203 | 153 | break; |
| 204 | 154 | |
| 205 | 155 | case 'livestream': |
| 206 | 156 | if ( empty( $params['src'] ) ) { |
| 207 | - return $this->get_error( __( 'A YouTube channel ID (or) a video URL from the channel is required.', 'automatic-youtube-gallery' ) ); | |
| 157 | + return $this->get_error( __( 'YouTube Channel ID (or) or a YouTube Video URL from the Channel is required.', 'automatic-youtube-gallery' ) ); | |
| 208 | 158 | } |
| 209 | 159 | |
| 210 | - // @handle URLs can't be resolved to a channel ID here (mirrors the client-side | |
| 211 | - // check in admin.js / gallery-form.php). | |
| 212 | - if ( false !== strpos( $params['src'], '@' ) ) { | |
| 213 | - return $this->get_error( __( 'YouTube @handle URLs aren’t supported here. Please enter a channel ID, a /channel/ URL, or a video URL from the channel.', 'automatic-youtube-gallery' ) ); | |
| 214 | - } | |
| 215 | - | |
| 216 | 160 | $params['channelId'] = $this->get_channel_id( $params ); |
| 217 | 161 | |
| 218 | 162 | if ( empty( $params['channelId'] ) ) { |
| 219 | - return $this->get_error( __( 'Invalid YouTube channel ID.', 'automatic-youtube-gallery' ) ); | |
| 163 | + return $this->get_error( __( 'Invalid YouTube Channel ID.', 'automatic-youtube-gallery' ) ); | |
| 220 | 164 | } |
| 221 | 165 | |
| 222 | 166 | // Get live video using the channel id |
| 223 | 167 | $response = $this->request_api_live_video( $params ); |
| @@ -224,9 +168,9 @@ | ||
| 224 | 168 | break; |
| 225 | 169 | |
| 226 | 170 | default: // video |
| 227 | 171 | if ( empty( $params['src'] ) ) { |
| 228 | - return $this->get_error( __( 'A YouTube video ID (or) URL is required.', 'automatic-youtube-gallery' ) ); | |
| 172 | + return $this->get_error( __( 'YouTube Video ID (or) URL is required.', 'automatic-youtube-gallery' ) ); | |
| 229 | 173 | } |
| 230 | 174 | |
| 231 | 175 | $response = $this->request_api_video( $params ); |
| 232 | 176 | break; |
| @@ -231,14 +175,8 @@ | ||
| 231 | 175 | $response = $this->request_api_video( $params ); |
| 232 | 176 | break; |
| 233 | 177 | } |
| 234 | 178 | |
| 235 | - // Advanced mode: enrich channel/playlist/username/search videos (which come from | |
| 236 | - // playlistItems.list / search.list and lack duration + live broadcast details). | |
| 237 | - if ( 'advanced' === $mode && ! isset( $response->error ) && ! empty( $response->videos ) && in_array( $params['type'], array( 'playlist', 'channel', 'username', 'search' ), true ) ) { | |
| 238 | - $response->videos = $this->enrich_video_details( $response->videos ); | |
| 239 | - } | |
| 240 | - | |
| 241 | 179 | return $response; |
| 242 | 180 | } |
| 243 | 181 | |
| 244 | 182 | /** |
| @@ -255,9 +193,9 @@ | ||
| 255 | 193 | $id = $url; |
| 256 | 194 | |
| 257 | 195 | switch ( $type ) { |
| 258 | 196 | case 'playlist': |
| 259 | - if ( preg_match( '/[?&]list=([^&]+)/', $url, $matches ) ) { | |
| 197 | + if ( preg_match( '/list=(.*)&?\/?/', $url, $matches ) ) { | |
| 260 | 198 | $id = $matches[1]; |
| 261 | 199 | } |
| 262 | 200 | break; |
| 263 | 201 | |
| @@ -281,18 +219,14 @@ | ||
| 281 | 219 | } |
| 282 | 220 | break; |
| 283 | 221 | |
| 284 | 222 | default: // video |
| 285 | - if ( wp_http_validate_url( $id ) ) { | |
| 286 | - $id = ''; | |
| 287 | - } | |
| 288 | - | |
| 289 | 223 | $url = parse_url( $url ); |
| 290 | 224 | |
| 291 | 225 | if ( array_key_exists( 'host', $url ) ) { |
| 292 | 226 | if ( 0 === strcasecmp( $url['host'], 'youtu.be' ) ) { |
| 293 | 227 | $id = substr( $url['path'], 1 ); |
| 294 | - } elseif ( 0 === strcasecmp( $url['host'], 'www.youtube.com' ) || 0 === strcasecmp( $url['host'], 'youtube.com' ) ) { | |
| 228 | + } elseif ( 0 === strcasecmp( $url['host'], 'www.youtube.com' ) ) { | |
| 295 | 229 | if ( isset( $url['query'] ) ) { |
| 296 | 230 | parse_str( $url['query'], $url['query'] ); |
| 297 | 231 | |
| 298 | 232 | if ( isset( $url['query']['v'] ) ) { |
| @@ -301,9 +235,10 @@ | ||
| 301 | 235 | } |
| 302 | 236 | |
| 303 | 237 | if ( empty( $id ) ) { |
| 304 | 238 | $url['path'] = explode( '/', substr( $url['path'], 1 ) ); |
| 305 | - if ( in_array( $url['path'][0], array( 'e', 'embed', 'v', 'shorts', 'live' ) ) ) { | |
| 239 | + | |
| 240 | + if ( in_array( $url['path'][0], array( 'e', 'embed', 'v' ) ) ) { | |
| 306 | 241 | $id = $url['path'][1]; |
| 307 | 242 | } |
| 308 | 243 | } |
| 309 | 244 | } |
| @@ -329,9 +264,12 @@ | ||
| 329 | 264 | // Get channel ID from a Video URL: https://www.youtube.com/watch?v=XXXXXXXXXX |
| 330 | 265 | $video_id = $this->parse_youtube_id_from_url( $params['src'], 'video' ); |
| 331 | 266 | |
| 332 | 267 | // Request from cache |
| 333 | - $channel_ids = ayg_get_option( 'ayg_channel_ids' ); | |
| 268 | + $channel_ids = get_option( 'ayg_channel_ids', array() ); | |
| 269 | + if ( ! is_array( $channel_ids ) ) { | |
| 270 | + $channel_ids = (array) $channel_ids; | |
| 271 | + } | |
| 334 | 272 | |
| 335 | 273 | if ( isset( $channel_ids[ $video_id ] ) && ! empty( $channel_ids[ $video_id ] ) ) { |
| 336 | 274 | return $channel_ids[ $video_id ]; |
| 337 | 275 | } |
| @@ -363,9 +301,9 @@ | ||
| 363 | 301 | // Process output |
| 364 | 302 | if ( $id = $videos[0]->channel_id ) { |
| 365 | 303 | // Store in cache |
| 366 | 304 | $channel_ids[ $video_id ] = $id; |
| 367 | - update_option( 'ayg_channel_ids', $channel_ids, false ); | |
| 305 | + update_option( 'ayg_channel_ids', $channel_ids ); | |
| 368 | 306 | } |
| 369 | 307 | } |
| 370 | 308 | |
| 371 | 309 | return $id; |
| @@ -380,9 +318,12 @@ | ||
| 380 | 318 | * @return mixed |
| 381 | 319 | */ |
| 382 | 320 | private function get_playlist_id( $params = array() ) { |
| 383 | 321 | // Request from cache |
| 384 | - $playlist_ids = ayg_get_option( 'ayg_playlist_ids' ); | |
| 322 | + $playlist_ids = get_option( 'ayg_playlist_ids', array() ); | |
| 323 | + if ( ! is_array( $playlist_ids ) ) { | |
| 324 | + $playlist_ids = (array) $playlist_ids; | |
| 325 | + } | |
| 385 | 326 | |
| 386 | 327 | $key = ''; |
| 387 | 328 | |
| 388 | 329 | if ( isset( $params['forUsername'] ) && ! empty( $params['forUsername'] ) ) { |
| @@ -428,9 +369,9 @@ | ||
| 428 | 369 | // Process output |
| 429 | 370 | if ( $id = $items[0]->contentDetails->relatedPlaylists->uploads ) { |
| 430 | 371 | // Store in cache |
| 431 | 372 | $playlist_ids[ $key ] = $id; |
| 432 | - update_option( 'ayg_playlist_ids', $playlist_ids, false ); | |
| 373 | + update_option( 'ayg_playlist_ids', $playlist_ids ); | |
| 433 | 374 | |
| 434 | 375 | // Return |
| 435 | 376 | return $id; |
| 436 | 377 | } |
| @@ -490,13 +431,14 @@ | ||
| 490 | 431 | */ |
| 491 | 432 | private function request_api_search( $params = array() ) { |
| 492 | 433 | $api_url = $this->get_api_url( 'search.list' ); |
| 493 | 434 | |
| 494 | - // Passed through unmodified: request_api() now runs every parameter through | |
| 495 | - // http_build_query(), which encodes the OR operator "|" to %7C on its own. Pre-encoding it | |
| 496 | - // here would be double encoded into %257C and break the search. | |
| 497 | - $params['q'] = $params['src']; | |
| 435 | + $params['q'] = $params['src']; | |
| 498 | 436 | |
| 437 | + if ( ! empty( $params['q'] ) ) { | |
| 438 | + $params['q'] = str_replace( '|', '%7C', $params['q'] ); | |
| 439 | + } | |
| 440 | + | |
| 499 | 441 | $params['type'] = 'video'; // Overrides user defined type value 'search' |
| 500 | 442 | |
| 501 | 443 | $api_params = $this->safe_merge_params( |
| 502 | 444 | array( |
| @@ -505,15 +447,14 @@ | ||
| 505 | 447 | 'type' => 'video', |
| 506 | 448 | 'videoEmbeddable' => true, |
| 507 | 449 | 'part' => 'id,snippet', |
| 508 | 450 | 'order' => 'date', |
| 509 | - 'publishedAfter' => '', // Set by incremental sync to fetch only newly published videos | |
| 510 | 451 | 'maxResults' => 50, |
| 511 | 452 | 'pageToken' => '', |
| 512 | 453 | 'cache' => 0 |
| 513 | 454 | ), |
| 514 | 455 | $params |
| 515 | - ); | |
| 456 | + ); | |
| 516 | 457 | |
| 517 | 458 | $api_response = $this->request_api( $api_url, $api_params ); |
| 518 | 459 | if ( isset( $api_response->error ) ) { |
| 519 | 460 | return $api_response; |
| @@ -555,9 +496,9 @@ | ||
| 555 | 496 | ), |
| 556 | 497 | $params |
| 557 | 498 | ); |
| 558 | 499 | |
| 559 | - $api_response = $this->request_api( $api_url, $api_params, 'live' ); | |
| 500 | + $api_response = $this->request_api( $api_url, $api_params ); | |
| 560 | 501 | if ( isset( $api_response->error ) ) { |
| 561 | 502 | return $api_response; |
| 562 | 503 | } |
| 563 | 504 | |
| @@ -562,9 +503,9 @@ | ||
| 562 | 503 | } |
| 563 | 504 | |
| 564 | 505 | $videos = $this->parse_videos( $api_response ); |
| 565 | 506 | if ( isset( $videos->error ) ) { |
| 566 | - $livestream_settings = ayg_get_option( 'ayg_livestream_settings' ); | |
| 507 | + $livestream_settings = get_option( 'ayg_livestream_settings' ); | |
| 567 | 508 | return $this->get_error( '<div class="ayg-livestream-fallback-message">' . $livestream_settings['fallback_message'] . '</div>' ); |
| 568 | 509 | } |
| 569 | 510 | |
| 570 | 511 | // Process output |
| @@ -623,14 +564,12 @@ | ||
| 623 | 564 | */ |
| 624 | 565 | private function request_api_videos( $params = array() ) { |
| 625 | 566 | $api_url = $this->get_api_url( 'videos.list' ); |
| 626 | 567 | |
| 627 | - // Accept the video list separated by commas, spaces, or newlines (one per line) in any | |
| 628 | - // combination and line-ending style. The old "\n\r" replace looked for LF+CR (reversed), | |
| 629 | - // so a one-per-line list never split — it collapsed into a single invalid ID and returned | |
| 630 | - // "No videos found". Split on any run of whitespace or commas and drop empties instead. | |
| 631 | - $urls = preg_split( '/[\s,]+/', trim( (string) $params['src'] ), -1, PREG_SPLIT_NO_EMPTY ); | |
| 632 | - $urls = is_array( $urls ) ? $urls : array(); | |
| 568 | + $urls = str_replace( "\n\r", ',', $params['src'] ); | |
| 569 | + $urls = str_replace( ' ', ',', $urls ); | |
| 570 | + $urls = explode( ',', $urls ); | |
| 571 | + $urls = array_filter( $urls ); | |
| 633 | 572 | |
| 634 | 573 | $all_ids = array(); |
| 635 | 574 | foreach ( $urls as $url ) { |
| 636 | 575 | $all_ids[] = $this->parse_youtube_id_from_url( $url, 'video' ); |
| @@ -641,9 +580,12 @@ | ||
| 641 | 580 | $current_page = isset( $params['pageToken'] ) ? (int) $params['pageToken'] : 1; |
| 642 | 581 | $current_page = max( $current_page, 1 ); |
| 643 | 582 | $current_page = min( $current_page, $total_pages ); |
| 644 | 583 | |
| 645 | - $offset = max( 0, ( $current_page - 1 ) * $params['maxResults'] ); | |
| 584 | + $offset = ( $current_page - 1 ) * $params['maxResults']; | |
| 585 | + if ( $offset < 0 ) { | |
| 586 | + $offset = 0; | |
| 587 | + } | |
| 646 | 588 | |
| 647 | 589 | $current_ids = array_slice( $all_ids, $offset, $params['maxResults'] ); |
| 648 | 590 | $params['id'] = implode( ',', $current_ids ); |
| 649 | 591 | |
| @@ -670,11 +612,9 @@ | ||
| 670 | 612 | $response = new stdClass(); |
| 671 | 613 | $response->videos = $videos; |
| 672 | 614 | |
| 673 | 615 | $response->page_info = array( |
| 674 | - 'videos_found' => $total_videos, | |
| 675 | - 'total_pages' => $total_pages, | |
| 676 | - 'paged' => $current_page | |
| 616 | + 'videos_found' => $total_videos | |
| 677 | 617 | ); |
| 678 | 618 | |
| 679 | 619 | if ( $current_page > 1 ) { |
| 680 | 620 | $response->page_info['prev_page_token'] = $current_page - 1; |
| @@ -685,174 +625,8 @@ | ||
| 685 | 625 | } |
| 686 | 626 | |
| 687 | 627 | return $response; |
| 688 | 628 | } |
| 689 | - | |
| 690 | - /** | |
| 691 | - * Get videos from our custom database table "{$wpdb->prefix}ayg_videos". | |
| 692 | - * | |
| 693 | - * @since 2.5.7 | |
| 694 | - * @access private | |
| 695 | - * @param array $params Array of query params. | |
| 696 | - * @return stdClass | |
| 697 | - */ | |
| 698 | - private function get_videos_from_db( $params = array() ) { | |
| 699 | - global $wpdb; | |
| 700 | - | |
| 701 | - $videos_table = $wpdb->prefix . 'ayg_videos'; | |
| 702 | - $rel_table = $wpdb->prefix . 'ayg_gallery_relationships'; | |
| 703 | - | |
| 704 | - $gallery_id = $params['uid']; | |
| 705 | - | |
| 706 | - // Base query: every video linked to this gallery. An optional search term (the search | |
| 707 | - // form) narrows it by title/description; the "db" source type passes none and gets all. | |
| 708 | - $where = 'r.gallery_id = %s'; | |
| 709 | - $values = array( $gallery_id ); | |
| 710 | - | |
| 711 | - if ( ! empty( $params['searchTerm'] ) ) { | |
| 712 | - $search_term = '%' . $wpdb->esc_like( $params['searchTerm'] ) . '%'; | |
| 713 | - | |
| 714 | - $where .= ' AND (v.title LIKE %s OR v.description LIKE %s)'; | |
| 715 | - $values[] = $search_term; | |
| 716 | - $values[] = $search_term; | |
| 717 | - } | |
| 718 | - | |
| 719 | - // Optional duration filter. Whitelisted operator; value parameterized. Affects count + select. | |
| 720 | - $duration_filter = isset( $params['duration_filter'] ) ? $params['duration_filter'] : ''; | |
| 721 | - $duration = isset( $params['duration'] ) ? (int) $params['duration'] : 0; | |
| 722 | - | |
| 723 | - if ( $duration > 0 && in_array( $duration_filter, array( 'long', 'short' ), true ) ) { | |
| 724 | - $where .= ( 'long' === $duration_filter ) ? ' AND v.duration_seconds > %d' : ' AND v.duration_seconds < %d'; | |
| 725 | - $values[] = $duration; | |
| 726 | - } | |
| 727 | - | |
| 728 | - // Get Total Videos Count | |
| 729 | - $total_videos = $wpdb->get_var( | |
| 730 | - $wpdb->prepare( | |
| 731 | - "SELECT COUNT(*) | |
| 732 | - FROM $videos_table AS v | |
| 733 | - INNER JOIN $rel_table AS r ON v.video_id = r.video_id | |
| 734 | - WHERE $where", | |
| 735 | - $values | |
| 736 | - ) | |
| 737 | - ); | |
| 738 | - | |
| 739 | - if ( empty( $total_videos ) ) { | |
| 740 | - return $this->get_error( __( 'No videos found matching your query.', 'automatic-youtube-gallery' ) ); | |
| 741 | - } | |
| 742 | - | |
| 743 | - // Fetch Paginated Videos | |
| 744 | - $limit = (int) $params['maxResults']; | |
| 745 | - | |
| 746 | - if ( $limit <= 0 ) { | |
| 747 | - // 0 = show all videos on a single page (Gallery Builder "unlimited" per page). | |
| 748 | - // A LIMIT of the total count avoids the empty result set that LIMIT 0 would return. | |
| 749 | - $limit = (int) $total_videos; | |
| 750 | - $total_pages = 1; | |
| 751 | - $current_page = 1; | |
| 752 | - $offset = 0; | |
| 753 | - } else { | |
| 754 | - $total_pages = ceil( $total_videos / $limit ); | |
| 755 | - | |
| 756 | - $current_page = isset( $params['pageToken'] ) ? (int) $params['pageToken'] : 1; | |
| 757 | - $current_page = max( $current_page, 1 ); | |
| 758 | - $current_page = min( $current_page, $total_pages ); | |
| 759 | - | |
| 760 | - $offset = max( 0, ( $current_page - 1 ) * $limit ); | |
| 761 | - } | |
| 762 | - | |
| 763 | - // Display-time ordering. Whitelisted (ORDER BY can't be parameterized); v.id breaks ties. | |
| 764 | - $orderby_map = array( | |
| 765 | - 'date' => 'v.published_at_datetime', | |
| 766 | - 'title' => 'v.title', | |
| 767 | - 'duration' => 'v.duration_seconds' | |
| 768 | - ); | |
| 769 | - | |
| 770 | - $sort_by_raw = isset( $params['sort_by'] ) ? $params['sort_by'] : 'date'; | |
| 771 | - $sort_order = ( isset( $params['sort_order'] ) && 'asc' === strtolower( $params['sort_order'] ) ) ? 'ASC' : 'DESC'; | |
| 772 | - | |
| 773 | - // Random: a seed (set per render in ayg_build_gallery) makes RAND(seed) stable across this | |
| 774 | - // gallery's own pagination/search, so pages don't repeat or skip videos. | |
| 775 | - $random_seed = 0; | |
| 776 | - | |
| 777 | - if ( 'random' === $sort_by_raw ) { | |
| 778 | - $random_seed = isset( $params['sort_seed'] ) ? (int) $params['sort_seed'] : 0; | |
| 779 | - $order_by = ( $random_seed > 0 ) ? 'RAND(%d)' : 'RAND()'; | |
| 780 | - } else { | |
| 781 | - $sort_by = isset( $orderby_map[ $sort_by_raw ] ) ? $orderby_map[ $sort_by_raw ] : 'v.published_at_datetime'; | |
| 782 | - $order_by = "$sort_by $sort_order, v.id $sort_order"; | |
| 783 | - } | |
| 784 | - | |
| 785 | - // Deeplinked video: pin it to the top of the list so page 1 starts with the shared video | |
| 786 | - // while the per-page count stays exact. The pin reorders the whole list (not just page 1), | |
| 787 | - // so paginated AJAX requests passing the same id never repeat or skip videos. Ignored | |
| 788 | - // while searching — search results are a fresh listing of their own. | |
| 789 | - $featured_video_id = ''; | |
| 790 | - | |
| 791 | - if ( empty( $params['searchTerm'] ) && ! empty( $params['featured_video_id'] ) ) { | |
| 792 | - $featured_video_id = (string) $params['featured_video_id']; | |
| 793 | - $order_by = '(v.video_id = %s) DESC, ' . $order_by; | |
| 794 | - } | |
| 795 | - | |
| 796 | - // Assemble placeholder values in SQL order: WHERE ..., [featured video], [seed], LIMIT, OFFSET. | |
| 797 | - $query_values = $values; | |
| 798 | - | |
| 799 | - if ( '' !== $featured_video_id ) { | |
| 800 | - $query_values[] = $featured_video_id; | |
| 801 | - } | |
| 802 | - | |
| 803 | - if ( $random_seed > 0 ) { | |
| 804 | - $query_values[] = $random_seed; | |
| 805 | - } | |
| 806 | - | |
| 807 | - $query_values[] = $limit; | |
| 808 | - $query_values[] = $offset; | |
| 809 | - | |
| 810 | - $query = $wpdb->prepare( | |
| 811 | - "SELECT v.* | |
| 812 | - FROM $videos_table AS v | |
| 813 | - INNER JOIN $rel_table AS r ON v.video_id = r.video_id | |
| 814 | - WHERE $where | |
| 815 | - ORDER BY $order_by | |
| 816 | - LIMIT %d OFFSET %d", | |
| 817 | - $query_values | |
| 818 | - ); | |
| 819 | - | |
| 820 | - $videos = $wpdb->get_results( $query ); | |
| 821 | - | |
| 822 | - if ( empty( $videos ) ) { | |
| 823 | - return $this->get_error( __( 'No videos found matching your query.', 'automatic-youtube-gallery' ) ); | |
| 824 | - } | |
| 825 | - | |
| 826 | - foreach ( $videos as $index => $video ) { | |
| 827 | - if ( ! empty( $video->thumbnails ) ) { | |
| 828 | - $videos[ $index ]->thumbnails = ayg_maybe_unserialize( $video->thumbnails ); | |
| 829 | - } | |
| 830 | - | |
| 831 | - // Backward compat: templates reference $video->id as the YouTube video ID. | |
| 832 | - $videos[ $index ]->id = $video->video_id; | |
| 833 | - } | |
| 834 | - | |
| 835 | - // Process output | |
| 836 | - $response = new stdClass(); | |
| 837 | - $response->videos = $videos; | |
| 838 | - | |
| 839 | - $response->page_info = array( | |
| 840 | - 'videos_found' => $total_videos, | |
| 841 | - 'total_pages' => $total_pages, | |
| 842 | - 'paged' => $current_page | |
| 843 | - ); | |
| 844 | - | |
| 845 | - if ( $current_page > 1 ) { | |
| 846 | - $response->page_info['prev_page_token'] = $current_page - 1; | |
| 847 | - } | |
| 848 | - | |
| 849 | - if ( $current_page < $total_pages ) { | |
| 850 | - $response->page_info['next_page_token'] = $current_page + 1; | |
| 851 | - } | |
| 852 | - | |
| 853 | - return $response; | |
| 854 | - } | |
| 855 | 629 | |
| 856 | 630 | /** |
| 857 | 631 | * Get API URL by request. |
| 858 | 632 | * |
| @@ -871,34 +645,18 @@ | ||
| 871 | 645 | * @since 1.0.0 |
| 872 | 646 | * @access private |
| 873 | 647 | * @param string $url YouTube API URL. |
| 874 | 648 | * @param array $params Array of query params. |
| 875 | - * @param string $context "channel_id", "playlist_id", "videos", or "live" | |
| 649 | + * @param string $context "channel_id", "playlist_id", or "videos" | |
| 876 | 650 | * @return mixed |
| 877 | 651 | */ |
| 878 | 652 | private function request_api( $url, $params, $context = 'videos' ) { |
| 879 | 653 | $params['key'] = $this->api_key; |
| 880 | - | |
| 881 | - // Build API URL | |
| 882 | - $cache_duration = 0; | |
| 883 | - if ( isset( $params['cache'] ) ) { | |
| 884 | - $cache_duration = (int) $params['cache']; | |
| 885 | - unset( $params['cache'] ); | |
| 886 | - } | |
| 887 | - $cache_duration = min( $cache_duration, 2419200 ); // Max cache duration: 1 Month | |
| 888 | 654 | |
| 889 | - // Every parameter — the search term "q" included — goes through http_build_query() so it is | |
| 890 | - // URL encoded. "q" used to be appended to the URL raw, which meant a caller could smuggle | |
| 891 | - // extra parameters into the outbound request by putting "&" in the search keywords. | |
| 892 | - $api_url = $url . ( strpos( $url, '?' ) === false ? '?' : '&' ) . http_build_query( $params ); | |
| 893 | - | |
| 894 | - // Prefix the cache key with the gallery uid so a single gallery's transients can be cleared | |
| 895 | - // on demand (e.g. saving a live search/livestream gallery) via ayg_delete_cache( $uid ). | |
| 896 | - $cache_uid = isset( $this->params['uid'] ) ? (string) $this->params['uid'] : ''; | |
| 897 | - $cache_key = 'ayg_' . ( '' !== $cache_uid ? $cache_uid . '_' : '' ) . md5( $api_url ); | |
| 898 | - | |
| 899 | 655 | // Request from cache |
| 900 | - if ( ! $this->is_development_mode && $cache_duration > 0 ) { | |
| 656 | + if ( ! $this->is_development_mode ) { | |
| 657 | + $cache_url = $url . ( strpos( $url, '?' ) === false ? '?' : '' ) . http_build_query( $params ); | |
| 658 | + $cache_key = 'ayg_' . md5( $cache_url ); | |
| 901 | 659 | $cache_data = get_transient( $cache_key ); |
| 902 | 660 | |
| 903 | 661 | if ( ! empty( $cache_data ) ) { |
| 904 | 662 | return $cache_data; |
| @@ -905,13 +663,27 @@ | ||
| 905 | 663 | } |
| 906 | 664 | } |
| 907 | 665 | |
| 908 | 666 | // Request from API |
| 909 | - $timeout = apply_filters( 'ayg_api_request_timeout', 15 ); | |
| 910 | - | |
| 911 | - $request = wp_remote_get( $api_url, array( | |
| 667 | + $cache_duration = 0; | |
| 668 | + if ( isset( $params['cache'] ) ) { | |
| 669 | + $cache_duration = (int) $params['cache']; | |
| 670 | + unset( $params['cache'] ); | |
| 671 | + } | |
| 672 | + | |
| 673 | + $q = ''; | |
| 674 | + if ( isset( $params['q'] ) ) { | |
| 675 | + $q = $params['q']; | |
| 676 | + unset( $params['q'] ); | |
| 677 | + } | |
| 678 | + | |
| 679 | + $url = $url . ( strpos( $url, '?' ) === false ? '?' : '' ) . http_build_query( $params ); | |
| 680 | + if ( ! empty( $q ) ) { | |
| 681 | + $url .= '&q=' . $q; | |
| 682 | + } | |
| 683 | + | |
| 684 | + $request = wp_remote_get( $url, array( | |
| 912 | 685 | 'headers' => [ 'referer' => home_url() ], |
| 913 | - 'timeout' => $timeout, // Increase timeout if needed | |
| 914 | 686 | ) ); |
| 915 | 687 | |
| 916 | 688 | if ( is_wp_error( $request ) ) { |
| 917 | 689 | return $this->get_error( $request->get_error_message() ); |
| @@ -917,14 +689,11 @@ | ||
| 917 | 689 | return $this->get_error( $request->get_error_message() ); |
| 918 | 690 | } |
| 919 | 691 | |
| 920 | 692 | $body = wp_remote_retrieve_body( $request ); |
| 693 | + | |
| 921 | 694 | $data = json_decode( $body ); |
| 922 | 695 | |
| 923 | - if ( empty( $data ) ) { | |
| 924 | - return $this->get_error( __( 'Empty or invalid API response', 'automatic-youtube-gallery' ) ); | |
| 925 | - } | |
| 926 | - | |
| 927 | 696 | if ( isset( $data->error ) ) { |
| 928 | 697 | $message = "Error " . $data->error->code . " " . $data->error->message; |
| 929 | 698 | |
| 930 | 699 | if ( isset( $data->error->errors[0] ) ) { |
| @@ -934,55 +703,31 @@ | ||
| 934 | 703 | return $this->get_error( $message ); |
| 935 | 704 | } |
| 936 | 705 | |
| 937 | 706 | // Store in cache (transients) |
| 938 | - $cache_enabled = false; | |
| 707 | + if ( ! $this->is_development_mode && 'videos' == $context && $cache_duration > 0 ) { | |
| 708 | + if ( isset( $data->items ) && is_array( $data->items ) && count( $data->items ) > 0 ) { | |
| 709 | + set_transient( $cache_key, $data, $cache_duration ); | |
| 939 | 710 | |
| 940 | - if ( ! $this->is_development_mode && $cache_duration > 0 ) { | |
| 941 | - if ( 'videos' === $context ) { | |
| 942 | - if ( ! empty( $data->items ) && is_array( $data->items ) ) { | |
| 943 | - $cache_enabled = true; | |
| 711 | + // Get the current list of transients | |
| 712 | + $cache_keys = get_option( 'ayg_transient_keys', array() ); | |
| 713 | + if ( ! is_array( $cache_keys ) ) { | |
| 714 | + $cache_keys = (array) $cache_keys; | |
| 944 | 715 | } |
| 945 | - } | |
| 946 | 716 | |
| 947 | - if ( 'live' === $context ) { | |
| 948 | - $cache_enabled = true; | |
| 949 | - } | |
| 950 | - } | |
| 717 | + // Append our new one | |
| 718 | + if ( ! in_array( $cache_key, $cache_keys ) ) { | |
| 719 | + $cache_keys[] = $cache_key; | |
| 720 | + } | |
| 951 | 721 | |
| 952 | - if ( $cache_enabled ) { | |
| 953 | - set_transient( $cache_key, $data, $cache_duration ); | |
| 954 | - | |
| 955 | - // Get the current list of transients | |
| 956 | - $cache_keys = ayg_get_option( 'ayg_transient_keys' ); | |
| 957 | - | |
| 958 | - // Append our new one | |
| 959 | - if ( ! in_array( $cache_key, $cache_keys ) ) { | |
| 960 | - $cache_keys[] = $cache_key; | |
| 722 | + // Save it to the DB | |
| 723 | + update_option( 'ayg_transient_keys', $cache_keys ); | |
| 961 | 724 | } |
| 962 | - | |
| 963 | - // Save it to the DB (autoload=no: this list can grow large and is not needed on every page load) | |
| 964 | - update_option( 'ayg_transient_keys', $cache_keys, false ); | |
| 965 | 725 | } |
| 966 | 726 | |
| 967 | - // Store videos in our custom database table "{$wpdb->prefix}ayg_videos" | |
| 968 | - // | |
| 969 | - // What reaches the storage layer is rebuilt from an explicit allowlist instead of being | |
| 970 | - // handed the raw request params, so the allowlist that governs the outbound request now | |
| 971 | - // governs the database write made from the same function. Gallery membership ("uid") is | |
| 972 | - // the value that decides what a gallery displays, so it is only passed along when the | |
| 973 | - // caller opted in through "store" — never on the strength of a "uid" alone. | |
| 974 | - $store_attributes = array( | |
| 975 | - 'type' => isset( $this->params['type'] ) ? $this->params['type'] : '', | |
| 976 | - 'exclude' => ( isset( $this->params['exclude'] ) && is_array( $this->params['exclude'] ) ) ? $this->params['exclude'] : array() | |
| 977 | - ); | |
| 978 | - | |
| 979 | - if ( $this->can_store && ! empty( $this->params['uid'] ) ) { | |
| 980 | - $store_attributes['uid'] = (string) $this->params['uid']; | |
| 981 | - } | |
| 982 | - | |
| 983 | - ayg_db_store_videos( $data, $store_attributes ); | |
| 984 | - | |
| 727 | + // Store videos in our custom database table "{$wpdb->prefix}ayg_videos" | |
| 728 | + ayg_db_store_videos( $data ); | |
| 729 | + | |
| 985 | 730 | // Finally return the data |
| 986 | 731 | return $data; |
| 987 | 732 | } |
| 988 | 733 | |
| @@ -994,27 +739,24 @@ | ||
| 994 | 739 | * @param object $data YouTube API response object. |
| 995 | 740 | * @return mixed |
| 996 | 741 | */ |
| 997 | 742 | private function parse_videos( $data ) { |
| 998 | - if ( empty( $data->items ) || ! is_array( $data->items ) ) { | |
| 999 | - $error = $this->get_error( __( 'No videos found matching your query.', 'automatic-youtube-gallery' ) ); | |
| 743 | + if ( ! isset( $data->items ) ) { | |
| 744 | + return $this->get_error( __( 'No videos found matching your query.', 'automatic-youtube-gallery' ) ); | |
| 745 | + } | |
| 1000 | 746 | |
| 1001 | - // Flag an empty result set so an incremental sync can tell "nothing new" apart | |
| 1002 | - // from a genuine API failure (quota, bad source) and complete cleanly. | |
| 1003 | - $error->no_results = true; | |
| 1004 | - | |
| 1005 | - return $error; | |
| 747 | + $items = $data->items; | |
| 748 | + if ( ! is_array( $items ) || 0 == count( $items ) ) { | |
| 749 | + return $this->get_error( __( 'No videos found matching your query.', 'automatic-youtube-gallery' ) ); | |
| 1006 | 750 | } |
| 1007 | 751 | |
| 1008 | - $items = $data->items; | |
| 1009 | - $videos = array(); | |
| 1010 | - $exclude = ( isset( $this->params['exclude'] ) && is_array( $this->params['exclude'] ) ) ? $this->params['exclude'] : array(); | |
| 752 | + $videos = array(); | |
| 1011 | 753 | |
| 1012 | 754 | foreach ( $items as $item ) { |
| 1013 | 755 | $video = new stdClass(); |
| 1014 | 756 | |
| 1015 | 757 | // Video ID |
| 1016 | - $video->id = ''; | |
| 758 | + $video->id = ''; | |
| 1017 | 759 | |
| 1018 | 760 | if ( isset( $item->snippet->resourceId ) && isset( $item->snippet->resourceId->videoId ) ) { |
| 1019 | 761 | $video->id = $item->snippet->resourceId->videoId; |
| 1020 | 762 | } elseif ( isset( $item->contentDetails ) && isset( $item->contentDetails->videoId ) ) { |
| @@ -1022,16 +764,11 @@ | ||
| 1022 | 764 | } elseif ( isset( $item->id ) && isset( $item->id->videoId ) ) { |
| 1023 | 765 | $video->id = $item->id->videoId; |
| 1024 | 766 | } elseif ( isset( $item->id ) ) { |
| 1025 | 767 | $video->id = $item->id; |
| 1026 | - } | |
| 768 | + } | |
| 1027 | 769 | |
| 1028 | - // Skip videos on the gallery's exclude list | |
| 1029 | - if ( ayg_is_video_excluded( $video->id, $exclude ) ) { | |
| 1030 | - continue; | |
| 1031 | - } | |
| 1032 | - | |
| 1033 | - // Video channel ID | |
| 770 | + // Video channel ID | |
| 1034 | 771 | $video->channel_id = ''; |
| 1035 | 772 | |
| 1036 | 773 | if ( isset( $item->snippet->channelId ) ) { |
| 1037 | 774 | $video->channel_id = $item->snippet->channelId; |
| @@ -1078,68 +815,8 @@ | ||
| 1078 | 815 | return $videos; |
| 1079 | 816 | } |
| 1080 | 817 | |
| 1081 | 818 | /** |
| 1082 | - * Enrich parsed videos with duration and live broadcast details. | |
| 1083 | - * | |
| 1084 | - * playlistItems.list / search.list responses lack contentDetails.duration and | |
| 1085 | - * snippet.liveBroadcastContent, so this makes a supplementary videos.list request (1 quota | |
| 1086 | - * unit per 50 IDs) — updating the stored rows and merging duration + video_type into $videos. | |
| 1087 | - * | |
| 1088 | - * @since 2.8.0 | |
| 1089 | - * @access private | |
| 1090 | - * @param array $videos Parsed video objects from parse_videos(). | |
| 1091 | - * @return array The same videos, with duration / duration_seconds / video_type set. | |
| 1092 | - */ | |
| 1093 | - private function enrich_video_details( $videos ) { | |
| 1094 | - // Index by video ID for the merge. PHP holds objects by handle, so mutating a $map | |
| 1095 | - // entry below also updates the same instance in $videos (what we return). | |
| 1096 | - $map = array(); | |
| 1097 | - | |
| 1098 | - foreach ( $videos as $video ) { | |
| 1099 | - if ( ! empty( $video->id ) ) { | |
| 1100 | - $map[ $video->id ] = $video; | |
| 1101 | - } | |
| 1102 | - } | |
| 1103 | - | |
| 1104 | - if ( empty( $map ) ) { | |
| 1105 | - return $videos; | |
| 1106 | - } | |
| 1107 | - | |
| 1108 | - $api_url = $this->get_api_url( 'videos.list' ); | |
| 1109 | - | |
| 1110 | - // videos.list accepts up to 50 IDs per request. | |
| 1111 | - foreach ( array_chunk( array_keys( $map ), 50 ) as $chunk ) { | |
| 1112 | - $api_params = array( | |
| 1113 | - 'id' => implode( ',', $chunk ), | |
| 1114 | - 'part' => 'id,snippet,contentDetails,status' | |
| 1115 | - ); | |
| 1116 | - | |
| 1117 | - // request_api() also stores the enriched rows (videos.list response → | |
| 1118 | - // ayg_db_store_videos() writes duration_seconds + video_type). | |
| 1119 | - $api_response = $this->request_api( $api_url, $api_params ); | |
| 1120 | - | |
| 1121 | - if ( isset( $api_response->error ) || empty( $api_response->items ) || ! is_array( $api_response->items ) ) { | |
| 1122 | - continue; | |
| 1123 | - } | |
| 1124 | - | |
| 1125 | - foreach ( $api_response->items as $item ) { | |
| 1126 | - if ( empty( $item->id ) || ! isset( $map[ $item->id ] ) ) { | |
| 1127 | - continue; | |
| 1128 | - } | |
| 1129 | - | |
| 1130 | - $duration = isset( $item->contentDetails->duration ) ? $item->contentDetails->duration : ''; | |
| 1131 | - | |
| 1132 | - $map[ $item->id ]->duration = $duration; | |
| 1133 | - $map[ $item->id ]->duration_seconds = ayg_parse_duration_seconds( $duration ); | |
| 1134 | - $map[ $item->id ]->video_type = ! empty( $item->snippet->liveBroadcastContent ) ? $item->snippet->liveBroadcastContent : 'none'; | |
| 1135 | - } | |
| 1136 | - } | |
| 1137 | - | |
| 1138 | - return $videos; | |
| 1139 | - } | |
| 1140 | - | |
| 1141 | - /** | |
| 1142 | 819 | * Parse page info from the YouTube API response object. |
| 1143 | 820 | * |
| 1144 | 821 | * @since 1.0.0 |
| 1145 | 822 | * @access private |
| @@ -1146,27 +823,14 @@ | ||
| 1146 | 823 | * @param object $data YouTube API response object. |
| 1147 | 824 | * @return array |
| 1148 | 825 | */ |
| 1149 | 826 | private function parse_page_info( $data ) { |
| 1150 | - $page_info = array( | |
| 1151 | - 'videos_found' => 0 | |
| 1152 | - ); | |
| 827 | + $page_info = array(); | |
| 1153 | 828 | |
| 1154 | - // Total number of videos found | |
| 829 | + // Total count of videos found | |
| 1155 | 830 | if ( isset( $data->pageInfo ) && isset( $data->pageInfo->totalResults ) ) { |
| 1156 | - $page_info['videos_found'] = (int) $data->pageInfo->totalResults; | |
| 1157 | - } | |
| 1158 | - | |
| 1159 | - // Calculate total number of pages | |
| 1160 | - if ( $page_info['videos_found'] > 0 ) { | |
| 1161 | - if ( 'search' == $this->params['type'] ) { | |
| 1162 | - $limit = min( (int) $this->params['limit'], $page_info['videos_found'] ); | |
| 1163 | - $page_info['total_pages'] = ceil( $limit / (int) $this->params['maxResults'] ); | |
| 1164 | - } else { | |
| 1165 | - $max_results = (int) $this->params['maxResults']; | |
| 1166 | - $page_info['total_pages'] = ( $max_results <= 0 ) ? 1 : ceil( $page_info['videos_found'] / $max_results ); | |
| 1167 | - } | |
| 1168 | - } | |
| 831 | + $page_info['videos_found'] = $data->pageInfo->totalResults; | |
| 832 | + } | |
| 1169 | 833 | |
| 1170 | 834 | // Token for the previous page |
| 1171 | 835 | if ( isset( $data->prevPageToken ) ) { |
| 1172 | 836 | $page_info['prev_page_token'] = $data->prevPageToken; |