Advertisement
hmbashar

Youtube Feed with shortcode with cache

May 10th, 2025 (edited)
251
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 7.91 KB | None | 0 0
  1. <?php
  2. function fetch_youtube_videos_shortcode($atts) {
  3.     $atts = shortcode_atts([
  4.         'channel_id'   => '',
  5.         'playlist_id'  => '',
  6.         'max_results'  => 4,
  7.         'api_key'      => '',
  8.         'type'         => 'channel'
  9.     ], $atts);
  10.  
  11.     $api_key = $atts['api_key'];
  12.     $max     = intval($atts['max_results']);
  13.     $cache_key_success = 'youtube_cache_success_' . md5(serialize($atts));
  14.     $cache_key_error   = 'youtube_cache_error_' . md5(serialize($atts));
  15.  
  16.     // Try wp_cache first
  17.     $cached_videos = wp_cache_get($cache_key_success, 'youtube_videos');
  18.     if (!$cached_videos) {
  19.         $cached_videos = get_transient($cache_key_success);
  20.         if ($cached_videos) {
  21.             wp_cache_set($cache_key_success, $cached_videos, 'youtube_videos', 6 * HOUR_IN_SECONDS);
  22.         }
  23.     }
  24.  
  25.     if ($cached_videos) {
  26.         $body = $cached_videos;
  27.     } else {
  28.         // Check if error is cached
  29.         $cached_error = wp_cache_get($cache_key_error, 'youtube_videos');
  30.         if (!$cached_error) {
  31.             $cached_error = get_transient($cache_key_error);
  32.             if ($cached_error) {
  33.                 wp_cache_set($cache_key_error, $cached_error, 'youtube_videos', HOUR_IN_SECONDS);
  34.             }
  35.         }
  36.  
  37.         if ($cached_error) {
  38.             return esc_html($cached_error);
  39.         }
  40.  
  41.         // Build API URL
  42.         if ($atts['type'] === 'playlist' && $atts['playlist_id']) {
  43.             $url = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId={$atts['playlist_id']}&maxResults=50&key={$api_key}";
  44.         } elseif ($atts['type'] === 'channel' && $atts['channel_id']) {
  45.             // Removed videoDuration param here
  46.             $url = "https://www.googleapis.com/youtube/v3/search?key={$api_key}&channelId={$atts['channel_id']}&part=snippet,id&order=date&type=video&maxResults=20";
  47.         } else {
  48.             return 'Invalid settings. Please check your shortcode attributes.';
  49.         }
  50.  
  51.         $response = wp_remote_get($url);
  52.  
  53.         if (is_wp_error($response)) {
  54.             $error_message = 'Unable to fetch videos. Please try again later.';
  55.             $error_cache_duration = apply_filters('youtube_videos_error_cache_time', HOUR_IN_SECONDS);
  56.             wp_cache_set($cache_key_error, $error_message, 'youtube_videos', $error_cache_duration);
  57.             set_transient($cache_key_error, $error_message, $error_cache_duration);
  58.             return $error_message;
  59.         }
  60.  
  61.         $body = json_decode(wp_remote_retrieve_body($response));
  62.  
  63.         // For playlist type: sort by date & limit
  64.         if ($atts['type'] === 'playlist' && !empty($body->items)) {
  65.             $body->items = array_filter($body->items, function($item) {
  66.                 return isset($item->snippet->publishedAt);
  67.             });
  68.  
  69.             usort($body->items, function($a, $b) {
  70.                 return strtotime($b->snippet->publishedAt) - strtotime($a->snippet->publishedAt);
  71.             });
  72.  
  73.             $body->items = array_slice($body->items, 0, $max);
  74.         }
  75.  
  76.         // For channel type: filter out Shorts based on duration
  77.         if ($atts['type'] === 'channel' && !empty($body->items)) {
  78.             $video_ids = [];
  79.             foreach ($body->items as $item) {
  80.                 $video_id = $item->id->videoId ?? '';
  81.                 if ($video_id) {
  82.                     $video_ids[] = $video_id;
  83.                 }
  84.             }
  85.  
  86.             if (!empty($video_ids)) {
  87.                 $videos_url = "https://www.googleapis.com/youtube/v3/videos?key={$api_key}&id=" . implode(',', $video_ids) . "&part=contentDetails";
  88.                 $videos_response = wp_remote_get($videos_url);
  89.  
  90.                 if (!is_wp_error($videos_response)) {
  91.                     $videos_body = json_decode(wp_remote_retrieve_body($videos_response));
  92.                     $durations = [];
  93.                     foreach ($videos_body->items as $video_item) {
  94.                         $durations[$video_item->id] = $video_item->contentDetails->duration;
  95.                     }
  96.  
  97.                     // Filter out Shorts (<= 60 sec)
  98.                     $filtered_items = [];
  99.                     foreach ($body->items as $item) {
  100.                         $video_id = $item->id->videoId ?? '';
  101.                         if (!$video_id || !isset($durations[$video_id])) continue;
  102.  
  103.                         try {
  104.                             $interval = new DateInterval($durations[$video_id]);
  105.                             $seconds = ($interval->h * 3600) + ($interval->i * 60) + $interval->s;
  106.                         } catch (Exception $e) {
  107.                             $seconds = 0; // Fallback if parsing fails
  108.                         }
  109.  
  110.                         if ($seconds > 60) { // Keep videos longer than 60 sec (not Shorts)
  111.                             $filtered_items[] = $item;
  112.                         }
  113.                     }
  114.  
  115.                     // Slice to max results
  116.                     $body->items = array_slice($filtered_items, 0, $max);
  117.                 }
  118.             }
  119.         }
  120.  
  121.         if (isset($body->error)) {
  122.             $error_code    = $body->error->code ?? '';
  123.             $error_message = $body->error->message ?? 'YouTube API error occurred.';
  124.  
  125.             if (in_array($error_code, [403, 429])) {
  126.                 $error_message = 'YouTube API quota limit reached. Please check back later.';
  127.                 $quota_cache_duration = apply_filters('youtube_videos_quota_cache_time', DAY_IN_SECONDS);
  128.                 wp_cache_set($cache_key_error, $error_message, 'youtube_videos', $quota_cache_duration);
  129.                 set_transient($cache_key_error, $error_message, $quota_cache_duration);
  130.             } else {
  131.                 $error_cache_duration = apply_filters('youtube_videos_error_cache_time', HOUR_IN_SECONDS);
  132.                 wp_cache_set($cache_key_error, $error_message, 'youtube_videos', $error_cache_duration);
  133.                 set_transient($cache_key_error, $error_message, $error_cache_duration);
  134.             }
  135.  
  136.             return esc_html($error_message);
  137.         }
  138.  
  139.         if (!empty($body->items)) {
  140.             $success_cache_duration = apply_filters('youtube_videos_success_cache_time', 6 * HOUR_IN_SECONDS);
  141.             wp_cache_set($cache_key_success, $body, 'youtube_videos', $success_cache_duration);
  142.             set_transient($cache_key_success, $body, $success_cache_duration);
  143.         } else {
  144.             $empty_cache_duration = apply_filters('youtube_videos_empty_cache_time', 30 * MINUTE_IN_SECONDS);
  145.             wp_cache_set($cache_key_error, 'No videos found.', 'youtube_videos', $empty_cache_duration);
  146.             set_transient($cache_key_error, 'No videos found.', $empty_cache_duration);
  147.             return 'No videos found.';
  148.         }
  149.     }
  150.  
  151.     // Generate HTML
  152.     $html = '<div class="youtube-video-widget" style="display:flex; flex-wrap:nowrap; gap:20px; overflow-x:auto; justify-content:space-between; font-family:\'Fira Sans Condensed\', sans-serif;">';
  153.  
  154.     foreach ($body->items as $item) {
  155.         $snippet = $item->snippet;
  156.         $video_id = ($atts['type'] === 'playlist') ? $snippet->resourceId->videoId : ($item->id->videoId ?? '');
  157.         if (!$video_id) continue;
  158.  
  159.         $title = esc_html($snippet->title);
  160.         $thumb = esc_url($snippet->thumbnails->medium->url);
  161.         $link = "https://www.youtube.com/watch?v={$video_id}";
  162.  
  163.         $html .= "<div style='flex:1 0 24%; max-width:24%;'>
  164.                    <a href='{$link}' target='_blank' style='text-decoration:none;color:#000;'>
  165.                        <img src='{$thumb}' alt='{$title}' style='width:100%;border-radius:8px;'>
  166.                        <p style='margin-top:8px;font-weight:600;font-size:19px;font-family:\"Fira Sans Condensed\", sans-serif;'>{$title}</p>
  167.                    </a>
  168.                  </div>";
  169.     }
  170.  
  171.     $html .= '</div>';
  172.  
  173.     return $html;
  174. }
  175. add_shortcode('youtube_videos', 'fetch_youtube_videos_shortcode');
  176.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement