| 1 |
<?php |
| 2 |
|
| 3 |
if ( ! defined( 'ABSPATH' ) ) { |
| 4 |
exit; |
| 5 |
} |
| 6 |
|
| 7 |
class FV_Player_YouTube { |
| 8 |
|
| 9 |
static $instance = null; |
| 10 |
|
| 11 |
var $bYoutube = false; |
| 12 |
|
| 13 |
var $fTimeSpent_AutoSplash = 0; |
| 14 |
|
| 15 |
public static function _get_instance() { |
| 16 |
if( !self::$instance ) { |
| 17 |
self::$instance = new self(); |
| 18 |
} |
| 19 |
|
| 20 |
return self::$instance; |
| 21 |
} |
| 22 |
|
| 23 |
function __construct() { |
| 24 |
|
| 25 |
if( !is_admin() ) { |
| 26 |
// Load splash via API if not provided |
| 27 |
add_filter( 'fv_flowplayer_splash', array( $this, 'get__cached_splash' ), 10, 2 ); |
| 28 |
add_filter( 'fv_flowplayer_playlist_splash', array( $this, 'get__cached_splash' ), 10, 2 ); |
| 29 |
} |
| 30 |
|
| 31 |
// Fallback YouTube splash screen if no API key provided |
| 32 |
add_filter( 'fv_flowplayer_splash', array( $this, 'youtube_splash' ), 10, 2 ); |
| 33 |
add_filter( 'fv_flowplayer_playlist_splash', array( $this, 'youtube_splash' ), 10, 2 ); |
| 34 |
|
| 35 |
add_action( 'init', array( $this, 'disable_pro_plugin_hooks' ) ); |
| 36 |
|
| 37 |
add_action( 'admin_init', array( $this, 'admin__add_meta_boxes' ) ); |
| 38 |
|
| 39 |
//add_action( 'amp_post_template_footer', array( $this, 'amp_post_template_footer' ), 9 ); |
| 40 |
|
| 41 |
add_filter( 'fv_flowplayer_attributes', array( $this, 'player_attributes' ), 10, 3 ); |
| 42 |
|
| 43 |
add_filter( 'fv_player_item', array($this, 'player_item'), 10, 3 ); |
| 44 |
|
| 45 |
add_filter( 'fv_flowplayer_checker_time', array( $this, 'youtube_duration' ), 10, 2 ); |
| 46 |
|
| 47 |
add_filter( 'fv_flowplayer_args', array( $this, 'disable_titles_youtube') ); |
| 48 |
|
| 49 |
add_filter( 'fv_flowplayer_get_mime_type', array( $this, 'set_file_type'), 10, 2 ); |
| 50 |
|
| 51 |
add_action( 'fv_player_extensions_admin_load_assets', array( $this, 'admin_load_assets' ) ); |
| 52 |
|
| 53 |
add_filter( 'fv_flowplayer_conf', array($this, 'fv_flowplayer_conf'), 10, 2); |
| 54 |
|
| 55 |
add_filter( 'fv_player_meta_data', array($this, 'fetch_yt_data'), 10, 3); |
| 56 |
|
| 57 |
//add_action( 'wp_footer', array( $this, 'scripts' ), 0 ); |
| 58 |
|
| 59 |
} |
| 60 |
|
| 61 |
function admin__add_meta_boxes() { |
| 62 |
add_meta_box( 'fv_player_youtube', __('YouTube', 'fv-player-pro'), array( $this, 'fv_player_admin_youtube' ), 'fv_flowplayer_settings_hosting', 'normal' ); |
| 63 |
} |
| 64 |
|
| 65 |
/* |
| 66 |
* Triggered when loading the FV Player editor, we will need the |
| 67 |
* editor scripts and the player scripts as well - for preview. |
| 68 |
*/ |
| 69 |
function admin_load_assets() { |
| 70 |
global $fv_wp_flowplayer_ver; |
| 71 |
wp_enqueue_script('fvplayer-shortcode-editor-youtube', plugins_url('js/shortcode-editor-youtube.js', dirname(__FILE__) ),array('jquery','fvwpflowplayer-shortcode-editor'), $fv_wp_flowplayer_ver ); |
| 72 |
|
| 73 |
//$this->scripts(); |
| 74 |
} |
| 75 |
|
| 76 |
function amp_post_template_footer() { |
| 77 |
$this->scripts(); |
| 78 |
} |
| 79 |
|
| 80 |
function disable_pro_plugin_hooks() { |
| 81 |
if ( function_exists( 'FV_Player_Pro' ) ) { |
| 82 |
remove_filter( 'fv_flowplayer_splash', array( FV_Player_Pro(), 'youtube_splash' ), 10, 2 ); |
| 83 |
remove_filter( 'fv_flowplayer_playlist_splash', array( FV_Player_Pro(), 'youtube_splash' ), 10, 2 ); |
| 84 |
} |
| 85 |
} |
| 86 |
|
| 87 |
function disable_titles_youtube( $aArgs ) { |
| 88 |
global $fv_fp; |
| 89 |
|
| 90 |
// we don't want to avoid caption if it's set in lightbox anchor |
| 91 |
if( isset($aArgs['lightbox']) && $aArgs['lightbox'] ) { |
| 92 |
$aLightbox = preg_split('~[;]~', $aArgs['lightbox']); |
| 93 |
|
| 94 |
$bUseAnchor = false; |
| 95 |
foreach ($aLightbox AS $k => $i) { |
| 96 |
if ($i == 'text') { |
| 97 |
unset($aLightbox[$k]); |
| 98 |
$bUseAnchor = true; |
| 99 |
} |
| 100 |
} |
| 101 |
|
| 102 |
if( $bUseAnchor ) { |
| 103 |
return $aArgs; |
| 104 |
} |
| 105 |
} |
| 106 |
|
| 107 |
if( isset($aArgs['src']) && $this->is_youtube($aArgs['src']) && $fv_fp->_get_option( array('pro','youtube_titles_disable') )) { |
| 108 |
$aArgs['caption'] = ''; |
| 109 |
} |
| 110 |
return $aArgs; |
| 111 |
} |
| 112 |
|
| 113 |
function fetch_yt_data($video, $post_id = false, $videoObj = false ) { |
| 114 |
global $fv_fp; |
| 115 |
|
| 116 |
// must be url string |
| 117 |
if( !is_string($video) ) { |
| 118 |
return $video; |
| 119 |
} |
| 120 |
|
| 121 |
if ( $this->is_youtube($video) && $fv_fp->_get_option( array('pro','youtube_key') )) { |
| 122 |
|
| 123 |
$fv_flowplayer_meta = false; |
| 124 |
if( $post_id ) { |
| 125 |
$fv_flowplayer_meta = get_post_meta($post_id, flowplayer::get_video_key($video), true); |
| 126 |
if( !$fv_flowplayer_meta || !isset($fv_flowplayer_meta['date']) || ( $fv_flowplayer_meta['date'] + 24 * 3600 ) < time() || !$fv_flowplayer_meta['duration'] && ( $fv_flowplayer_meta['date'] + 60 ) < time() ) { |
| 127 |
$fv_flowplayer_meta = false; |
| 128 |
} |
| 129 |
} |
| 130 |
|
| 131 |
if( !$fv_flowplayer_meta ) { |
| 132 |
$tStart = microtime(true); |
| 133 |
$aId = $this->is_youtube($video); |
| 134 |
|
| 135 |
$api_url = add_query_arg( array( |
| 136 |
'part' => 'snippet,contentDetails,player', |
| 137 |
'id' => $aId[1], |
| 138 |
'key' => $fv_fp->_get_option( array('pro','youtube_key') ), |
| 139 |
'maxWidth' => 1920 // This is a trick to get player->embedWidth and embedHeight to be able to tell the aspect ratio of the video |
| 140 |
), 'https://www.googleapis.com/youtube/v3/videos' ); |
| 141 |
|
| 142 |
$response = wp_remote_get( $api_url, array( 'sslverify' => false ) ); |
| 143 |
|
| 144 |
$obj = is_wp_error($response) ? false : @json_decode( wp_remote_retrieve_body($response) ); |
| 145 |
|
| 146 |
if( isset($obj->error) && !empty($obj->error->message) ) { |
| 147 |
update_option('fv_player_pro_youtube_error', gmdate('r').": ".$obj->error->message, false ); |
| 148 |
} |
| 149 |
|
| 150 |
if( $obj && !empty($obj->items[0]) ) { |
| 151 |
$obj_item = $obj->items[0]; |
| 152 |
|
| 153 |
$fv_flowplayer_meta = array(); |
| 154 |
if ( !empty($obj_item->contentDetails->duration) ) { |
| 155 |
$duration = $obj_item->contentDetails->duration; |
| 156 |
|
| 157 |
if (class_exists('DateInterval')) { |
| 158 |
$interval = new DateInterval($duration); |
| 159 |
$fv_flowplayer_meta['duration'] = date_create('@0')->add($interval)->getTimestamp(); |
| 160 |
} else { |
| 161 |
$fv_flowplayer_meta['duration'] = flowplayer::hms_to_seconds($duration); |
| 162 |
} |
| 163 |
} |
| 164 |
|
| 165 |
$fv_flowplayer_meta['aspect_ratio'] = 0; |
| 166 |
if( !empty($obj_item->player->embedWidth) && !empty($obj_item->player->embedHeight) ) { |
| 167 |
$fv_flowplayer_meta['aspect_ratio'] = $obj_item->player->embedHeight/$obj_item->player->embedWidth; |
| 168 |
} |
| 169 |
|
| 170 |
$fv_flowplayer_meta['is_live'] = false; |
| 171 |
if( !empty($obj_item->snippet->liveBroadcastContent) ) { |
| 172 |
if( $obj_item->snippet->liveBroadcastContent == 'live' ) { |
| 173 |
$fv_flowplayer_meta['is_live'] = true; |
| 174 |
} |
| 175 |
} |
| 176 |
|
| 177 |
// YouTube splash screens come in various sizes and often with black borders. So we use the maxres image to determine image aspect ratio and then look for matching image |
| 178 |
if( !empty($obj_item->snippet->thumbnails) ) { |
| 179 |
$thumbs = $obj_item->snippet->thumbnails; |
| 180 |
$ratio = isset($thumbs->maxres) && intval($thumbs->maxres->width) > 0 && intval($thumbs->maxres->height) > 0 ? $thumbs->maxres->height/$thumbs->maxres->width : false; |
| 181 |
foreach( (array)$thumbs AS $k => $v ) { |
| 182 |
if( !$ratio || $v->height/$v->width == $ratio ) { |
| 183 |
$fv_flowplayer_meta['splash'] = $v->url; |
| 184 |
if( $v->width > 600 ) break; |
| 185 |
} |
| 186 |
} |
| 187 |
} |
| 188 |
|
| 189 |
$fv_flowplayer_meta['caption'] = !empty($obj_item->snippet->title) ? $obj_item->snippet->title : false; |
| 190 |
|
| 191 |
$fv_flowplayer_meta['author_thumbnail'] = false; |
| 192 |
$fv_flowplayer_meta['author_name'] = false; |
| 193 |
$fv_flowplayer_meta['author_url'] = false; |
| 194 |
|
| 195 |
// get channel id |
| 196 |
$channel_id = !empty($obj_item->snippet->channelId) ? $obj_item->snippet->channelId : false; |
| 197 |
|
| 198 |
$youtube_channel_obj = false; |
| 199 |
|
| 200 |
if( $channel_id ) { |
| 201 |
$api_url = add_query_arg( array( |
| 202 |
'part' => 'snippet', |
| 203 |
'id' => $channel_id, |
| 204 |
'key' => $fv_fp->_get_option( array('pro','youtube_key') ), |
| 205 |
), 'https://www.googleapis.com/youtube/v3/channels' ); |
| 206 |
|
| 207 |
|
| 208 |
$response = wp_remote_get( $api_url, array( 'sslverify' => false ) ); |
| 209 |
|
| 210 |
$youtube_channel_obj = is_wp_error($response) ? false : @json_decode( wp_remote_retrieve_body($response) ); |
| 211 |
} |
| 212 |
|
| 213 |
if ( $youtube_channel_obj && ! empty( $youtube_channel_obj->items[0]->snippet ) ) { |
| 214 |
$snippet = $youtube_channel_obj->items[0]->snippet; |
| 215 |
|
| 216 |
// get 'default' thumbnail |
| 217 |
$author_thumbnail_url = ! empty( $snippet->thumbnails->default->url) ? $snippet->thumbnails->default->url : false; |
| 218 |
|
| 219 |
// get channel name |
| 220 |
$author_name = ! empty( $snippet->title) ? $snippet->title : false; |
| 221 |
$fv_flowplayer_meta['author_name'] = $author_name; |
| 222 |
|
| 223 |
// get channel url |
| 224 |
$author_url = ! empty( $snippet->customUrl) ? 'https://www.youtube.com/' . $snippet->customUrl : false; |
| 225 |
$fv_flowplayer_meta['author_url'] = $author_url; |
| 226 |
|
| 227 |
if( $author_thumbnail_url && $author_name ) { // download channel thumbnail to media library |
| 228 |
global $FV_Player_Splash_Download, $wpdb; |
| 229 |
|
| 230 |
// check if author name is already in media library and use its post id as attachment id |
| 231 |
$youtube_channel_attachment_cache = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_fv_player_youtube_channel_id' AND meta_value = %s", $channel_id ) ); |
| 232 |
|
| 233 |
if( !empty($youtube_channel_attachment_cache) ) { |
| 234 |
$fv_flowplayer_meta['author_thumbnail'] = $youtube_channel_attachment_cache; |
| 235 |
} else { |
| 236 |
add_filter( 'upload_dir', array( $this, 'custom_upload_path' ) ); |
| 237 |
$author_thumbnail_attachment_data = $FV_Player_Splash_Download->download_splash( $author_thumbnail_url, $author_name ); |
| 238 |
remove_filter( 'upload_dir', array( $this, 'custom_upload_path' ) ); |
| 239 |
|
| 240 |
if( !empty($author_thumbnail_attachment_data) ) { |
| 241 |
$author_thumbnail_attachment_id = $author_thumbnail_attachment_data['attachment_id']; |
| 242 |
$fv_flowplayer_meta['author_thumbnail'] = $author_thumbnail_attachment_id; // store attachment id in video meta |
| 243 |
|
| 244 |
update_post_meta( $author_thumbnail_attachment_id, '_fv_player_youtube_channel_id', $channel_id ); // store splash url in attachment meta |
| 245 |
} |
| 246 |
} |
| 247 |
} |
| 248 |
} |
| 249 |
|
| 250 |
} |
| 251 |
|
| 252 |
$fv_flowplayer_meta['check_time'] = microtime(true) - $tStart; |
| 253 |
|
| 254 |
if ($post_id) { |
| 255 |
update_post_meta($post_id, flowplayer::get_video_key($video), $fv_flowplayer_meta); |
| 256 |
} |
| 257 |
} |
| 258 |
|
| 259 |
$videoData = false; |
| 260 |
if( !empty($fv_flowplayer_meta['splash']) && !empty($fv_flowplayer_meta['caption']) ) { |
| 261 |
$videoData = array( |
| 262 |
'name' => htmlspecialchars( str_replace( array(';','[',']'), array('\;','(',')'), $fv_flowplayer_meta['caption']) ), |
| 263 |
'thumbnail' => $fv_flowplayer_meta['splash'], |
| 264 |
'duration' => $fv_flowplayer_meta['duration'], |
| 265 |
'aspect_ratio' => $fv_flowplayer_meta['aspect_ratio'], |
| 266 |
'is_live' => $fv_flowplayer_meta['is_live'], |
| 267 |
'author_thumbnail' => $fv_flowplayer_meta['author_thumbnail'], |
| 268 |
'author_name' => $fv_flowplayer_meta['author_name'], |
| 269 |
'author_url' => $fv_flowplayer_meta['author_url'], |
| 270 |
// Note: No way of getting the actual video size unless you own the video and can use part=fileDetails |
| 271 |
); |
| 272 |
|
| 273 |
$videoData = apply_filters( 'fv_player_meta_data_youtube', $videoData, $video, $obj, $videoObj, $fv_flowplayer_meta ); |
| 274 |
} |
| 275 |
|
| 276 |
if( isset($obj->items[0]->snippet->liveBroadcastContent) && $obj->items[0]->snippet->liveBroadcastContent == 'live' ) { |
| 277 |
$videoData['is_live'] = true; |
| 278 |
} |
| 279 |
|
| 280 |
return $videoData; |
| 281 |
} else { |
| 282 |
return $video; // no vimeo or yt, pass to another filter |
| 283 |
} |
| 284 |
} |
| 285 |
|
| 286 |
function fv_flowplayer_conf( $conf ) { |
| 287 |
global $fv_fp; |
| 288 |
|
| 289 |
if( $this->bYoutube || $fv_fp->should_force_load_js() || did_action('fv_player_extensions_admin_load_assets') ) { |
| 290 |
$conf['youtube'] = true; |
| 291 |
|
| 292 |
if( $fv_fp->_get_option( array('pro','youtube_cookies') ) ) { |
| 293 |
$conf['youtube_cookies'] = true; |
| 294 |
} |
| 295 |
} |
| 296 |
return $conf; |
| 297 |
} |
| 298 |
|
| 299 |
function fv_player_admin_youtube() { |
| 300 |
global $fv_fp; |
| 301 |
|
| 302 |
$value = $fv_fp->_get_option('youtube_browser_chrome', 'standard'); |
| 303 |
?> |
| 304 |
<style> |
| 305 |
#fv_player_youtube .descriptions { |
| 306 |
float: right; |
| 307 |
position: relative; |
| 308 |
width: 50%; |
| 309 |
} |
| 310 |
|
| 311 |
#fv_player_youtube [data-describe] { |
| 312 |
display: none; |
| 313 |
position: absolute; |
| 314 |
top: 0; |
| 315 |
} |
| 316 |
</style> |
| 317 |
<table class="form-table2" style="margin: 5px; "> |
| 318 |
<tr> |
| 319 |
<td class="first"><label>YouTube UI:</label></td> |
| 320 |
<td> |
| 321 |
<?php |
| 322 |
$radio_butons = array(); |
| 323 |
$radio_butons_descriptions = array(); |
| 324 |
|
| 325 |
foreach( array( |
| 326 |
'standard' => array( |
| 327 |
'label' => __( 'Standard', 'fv-player' ), |
| 328 |
'description' => __( 'All of the YouTube embedded player interface will show, including related videos on pause.', 'fv-player' ) |
| 329 |
), |
| 330 |
'reduced' => array( |
| 331 |
'label' => __( 'Reduced', 'fv-player' ), |
| 332 |
'description' => __( 'Show only the video title and the YouTube logo.', 'fv-player' ) |
| 333 |
), |
| 334 |
'none' => array( |
| 335 |
'label' => __( 'None', 'fv-player' ), |
| 336 |
'description' => __( 'Remove everything.', 'fv-player' ) |
| 337 |
) |
| 338 |
) AS $key => $field ) { |
| 339 |
$id = 'youtube_browser_chrome_'.esc_attr($key); |
| 340 |
|
| 341 |
$radio_button = '<input id="'.$id.'" type="radio" name="youtube_browser_chrome" value="'.esc_attr($key).'"'; |
| 342 |
if( $value === $key || wp_json_encode($value) == $key ) { // use wp_json_encode as value can be boolean |
| 343 |
$radio_button .= ' checked="checked"'; |
| 344 |
} |
| 345 |
$radio_button .= '</input>'; |
| 346 |
$radio_button .= '<label for="'.$id.'">'.$field['label'].'</label><br />'; |
| 347 |
|
| 348 |
$radio_butons[] = $radio_button; |
| 349 |
|
| 350 |
if( !empty($field['description']) ) { |
| 351 |
$radio_butons_descriptions[$key] = $field['description']; |
| 352 |
} |
| 353 |
} |
| 354 |
|
| 355 |
echo '<div class="descriptions">'; |
| 356 |
foreach( $radio_butons_descriptions AS $key => $description ) { |
| 357 |
echo '<p class="description" data-describe="' . esc_attr( $key ) . '">' . esc_html( $description ).'</p>'; |
| 358 |
} |
| 359 |
echo '</div>'; |
| 360 |
|
| 361 |
echo implode( $radio_butons ); |
| 362 |
?> |
| 363 |
</td> |
| 364 |
</tr> |
| 365 |
<?php if( $fv_fp->_get_option( array('pro','youtube_titles_disable') ) ) $fv_fp->_get_checkbox(__('Disable video captions', 'fv-player-pro'), array('pro', 'youtube_titles_disable'), __('Normally the video title is parsed into the shortcode when saving the post, with this setting it won\'t appear.', 'fv-player-pro') ); ?> |
| 366 |
<?php $fv_fp->_get_checkbox(__("Use YouTube Cookies", 'fv-player-pro'), array('pro', 'youtube_cookies'), __("Otherwise FV Player Pro uses the youtube-nocookie.com domain to avoid use of YouTube cookies.", 'fv-player-pro') ); ?> |
| 367 |
|
| 368 |
<?php |
| 369 |
$fv_fp->_get_input_text( array( |
| 370 |
'key' => array( 'pro', 'youtube_key' ), |
| 371 |
'name' => __('Google Developer Key', 'fv-player-pro'), |
| 372 |
'first_td_class' => 'first', |
| 373 |
'help' => __('Required for a reliable YouTube splash screen and YouTube video duration parsing. Start a new project at <a href="https://console.developers.google.com/" target="_blank">Google Developers Console</a> and make sure YouTube Data API is enabled for the project.', 'fv-player-pro'), |
| 374 |
'secret' => true |
| 375 |
) ); |
| 376 |
?> |
| 377 |
|
| 378 |
<?php if( $sError = get_option('fv_player_pro_youtube_error') ) : ?> |
| 379 |
<tr> |
| 380 |
<td style="width: 250px"></td> |
| 381 |
<td> |
| 382 |
<p class="description"> |
| 383 |
<?php esc_html_e('Last Error', 'fv-player-pro'); ?>: <?php echo esc_html( $sError ); ?> |
| 384 |
</p> |
| 385 |
</td> |
| 386 |
</tr> |
| 387 |
<?php endif; ?> |
| 388 |
<?php if( !function_exists('FV_PLayer_Pro')): ?> |
| 389 |
<tr> |
| 390 |
<td colspan="4"> |
| 391 |
<a class="fv-wordpress-flowplayer-save button button-primary" href="#" style="margin-top: 2ex;"><?php esc_html_e( 'Save', 'fv-player' ); ?></a> |
| 392 |
</td> |
| 393 |
</tr> |
| 394 |
<?php endif; ?> |
| 395 |
<?php do_action('fv_player_youtube_inputs_after'); ?> |
| 396 |
</table> |
| 397 |
<div class="clear"></div> |
| 398 |
<script> |
| 399 |
jQuery( function($) { |
| 400 |
show_description_youtube_chrome(); |
| 401 |
|
| 402 |
$('[name=youtube_browser_chrome]').on( 'change', show_description_youtube_chrome ); |
| 403 |
|
| 404 |
function show_description_youtube_chrome() { |
| 405 |
$( '#fv_player_youtube [data-describe]' ).hide(); |
| 406 |
$( '#fv_player_youtube [data-describe='+$('[name=youtube_browser_chrome]:checked').val()+']' ).show(); |
| 407 |
} |
| 408 |
}); |
| 409 |
</script> |
| 410 |
<?php |
| 411 |
} |
| 412 |
|
| 413 |
function get__cached_splash( $splash, $src = false ) { |
| 414 |
global $post; |
| 415 |
|
| 416 |
if( !$splash && is_string($src) ) { |
| 417 |
|
| 418 |
$sVideoMeta = isset($post) ? get_post_meta( $post->ID, flowplayer::get_video_key($src, true ), true ) : false; |
| 419 |
if( !empty($sVideoMeta['splash']) ) { |
| 420 |
return $sVideoMeta['splash']; |
| 421 |
} |
| 422 |
|
| 423 |
// If we have no image we accept it if it's recent |
| 424 |
if( !empty($sVideoMeta['date']) && $sVideoMeta['date'] + 3600 > time() ) { |
| 425 |
return false; |
| 426 |
} |
| 427 |
|
| 428 |
if( $this->fTimeSpent_AutoSplash < 1 ) { |
| 429 |
global $post; |
| 430 |
if( $video_id = $this->is_youtube($src) ) { |
| 431 |
$video_id = $video_id[1]; |
| 432 |
$type = 'youtube'; |
| 433 |
} |
| 434 |
|
| 435 |
if( $video_id ) { |
| 436 |
$tStart = microtime(true); |
| 437 |
$splash = get_option('fv_player_'.$type.'_splash_'.$video_id); |
| 438 |
if( !$splash ) { |
| 439 |
$post_id = !empty($post->ID) ? $post->ID : false; |
| 440 |
|
| 441 |
$videoData = $this->fetch_yt_data($src, $post_id); |
| 442 |
if( $videoData && isset($videoData['thumbnail']) ) { |
| 443 |
$this->fTimeSpent_AutoSplash += microtime(true) - $tStart; |
| 444 |
update_option( 'fv_player_'.$type.'_splash_'.$video_id, $videoData['thumbnail'], false ); |
| 445 |
return $videoData['thumbnail']; |
| 446 |
} |
| 447 |
|
| 448 |
} else { |
| 449 |
return $splash; |
| 450 |
|
| 451 |
} |
| 452 |
|
| 453 |
} |
| 454 |
} |
| 455 |
} |
| 456 |
|
| 457 |
return $splash; |
| 458 |
} |
| 459 |
|
| 460 |
public function is_youtube( $sURL ) { |
| 461 |
|
| 462 |
if( |
| 463 |
preg_match( "~youtube.com/.*?(?:v|list)=([a-zA-Z0-9_-]+)(?:\?|$|&)~i", $sURL, $aDynamic ) || |
| 464 |
preg_match( "~youtube(?:-nocookie)?.com/(?:embed|live|shorts)/([a-zA-Z0-9_-]+)(?:\?|$|&)~i", $sURL, $aDynamic ) || |
| 465 |
preg_match( "~youtu.be/([a-zA-Z0-9_-]+)(?:\?|$|&)~i", $sURL, $aDynamic ) |
| 466 |
) { |
| 467 |
$this->bYoutube = true; |
| 468 |
return $aDynamic; |
| 469 |
} |
| 470 |
return false; |
| 471 |
} |
| 472 |
|
| 473 |
function player_attributes( $aAttributes, $media, $fv_fp ) { |
| 474 |
global $fv_fp; |
| 475 |
|
| 476 |
$aArgs = func_get_args(); |
| 477 |
|
| 478 |
if( isset($aArgs[2]->aCurArgs['src']) && $this->is_youtube($aArgs[2]->aCurArgs['src']) ) { |
| 479 |
$aAttributes['data-engine'] = 'fvyoutube'; |
| 480 |
$fv_fp->aCurArgs['engine'] = 'fvyoutube'; |
| 481 |
if( stripos($aAttributes['class'],' is-youtube') === false ) { |
| 482 |
$aAttributes['class'] .= ' is-youtube'; |
| 483 |
} |
| 484 |
} |
| 485 |
|
| 486 |
return $aAttributes; |
| 487 |
} |
| 488 |
|
| 489 |
function player_item($aItem, $index) { |
| 490 |
global $fv_fp; |
| 491 |
|
| 492 |
if( isset($aItem['sources'][0]['src']) && $this->is_youtube($aItem['sources'][0]['src']) ) { |
| 493 |
$video = $fv_fp->current_video(); |
| 494 |
|
| 495 |
if( !$video ) { |
| 496 |
return $aItem; |
| 497 |
} |
| 498 |
|
| 499 |
if ( 'reduced' === $fv_fp->_get_option('youtube_browser_chrome') ) { |
| 500 |
$attachment_id = $video->getMetaValue('author_thumbnail', true); |
| 501 |
$author_name = $video->getMetaValue('author_name', true); |
| 502 |
$author_url = $video->getMetaValue('author_url', true); |
| 503 |
|
| 504 |
if( $attachment_id) { |
| 505 |
$attachment_url = wp_get_attachment_url( $attachment_id ); |
| 506 |
if( $attachment_url ) { |
| 507 |
$aItem['author_thumbnail'] = sanitize_url( $attachment_url ); |
| 508 |
} |
| 509 |
} |
| 510 |
|
| 511 |
if( $author_name ) { |
| 512 |
$aItem['author_name'] = sanitize_text_field( $author_name ); |
| 513 |
} |
| 514 |
|
| 515 |
if( $author_url ) { |
| 516 |
$aItem['author_url'] = sanitize_url( $author_url) ; |
| 517 |
} |
| 518 |
} |
| 519 |
|
| 520 |
} |
| 521 |
|
| 522 |
return $aItem; |
| 523 |
} |
| 524 |
|
| 525 |
function scripts() { |
| 526 |
global $post; |
| 527 |
|
| 528 |
// todo: something better for video checker |
| 529 |
/*if( isset($GLOBALS['fv_fp_scripts']) && isset($GLOBALS['fv_fp_scripts']['fv_flowplayer_admin_test_media']) && count($GLOBALS['fv_fp_scripts']['fv_flowplayer_admin_test_media']) ) { |
| 530 |
foreach( $GLOBALS['fv_fp_scripts']['fv_flowplayer_admin_test_media'] AS $key => $item ) { |
| 531 |
if( !is_array($item[0]) && ( FV_Player_Pro_Vimeo()->is_vimeo(stripslashes($item[0])) || $this->is_youtube(stripslashes($item[0])) ) || apply_filters('fv_player_video_checker_exclude',false,$item[0]) ) { |
| 532 |
unset( $GLOBALS['fv_fp_scripts']['fv_flowplayer_admin_test_media'][$key] ); |
| 533 |
} |
| 534 |
} |
| 535 |
}*/ |
| 536 |
|
| 537 |
// Was there any player or do we expect any to load in Ajax? |
| 538 |
if( |
| 539 |
isset($GLOBALS['fv_fp_scripts']) || |
| 540 |
$this->should_force_load_js() |
| 541 |
) { |
| 542 |
|
| 543 |
// If we expect players to load in Ajax, YouTube API needs to |
| 544 |
// be there at all times |
| 545 |
if( $this->should_force_load_js() ) $this->bYoutube = 1; |
| 546 |
|
| 547 |
$aOptions = array( |
| 548 |
'youtube' => $this->bYoutube, |
| 549 |
); |
| 550 |
|
| 551 |
// TODO: Put bYouTube into fv_flowplayer_conf |
| 552 |
} |
| 553 |
} |
| 554 |
|
| 555 |
function set_file_type( $type ) { |
| 556 |
$args = func_get_args(); |
| 557 |
if( isset($args[1]) ) { |
| 558 |
if( $this->is_youtube($args[1]) ) { |
| 559 |
$type = "video/youtube"; |
| 560 |
} |
| 561 |
} |
| 562 |
return $type; |
| 563 |
} |
| 564 |
|
| 565 |
function youtube_duration( $iTime ) { |
| 566 |
return $iTime; |
| 567 |
|
| 568 |
$aArgs = func_get_args(); |
| 569 |
|
| 570 |
if( $iTime == 0 && $aId = $this->is_youtube($aArgs[1]) ) { |
| 571 |
$response = wp_remote_get( 'http://gdata.youtube.com/feeds/api/videos/'.$aId[1].'?v=2&alt=jsonc', array( 'sslverify' => false ) ); |
| 572 |
$obj = is_wp_error($response) ? false : @json_decode( wp_remote_retrieve_body($response) ); |
| 573 |
|
| 574 |
if( $obj && isset($obj->data->duration) ) { |
| 575 |
$iTime = $obj->data->duration; |
| 576 |
} |
| 577 |
|
| 578 |
} |
| 579 |
|
| 580 |
return $iTime; |
| 581 |
} |
| 582 |
|
| 583 |
function youtube_splash( $splash, $src = false ) { |
| 584 |
if( !$splash && is_string($src) && $res = $this->is_youtube($src) ) { |
| 585 |
return "https://i.ytimg.com/vi/".$res[1]."/maxresdefault.jpg#auto"; |
| 586 |
} |
| 587 |
return $splash; |
| 588 |
} |
| 589 |
|
| 590 |
public function custom_upload_path( $upload_dir ) { |
| 591 |
$upload_dir['path'] = $upload_dir['basedir'].'/fv-player-youtube-channels'; |
| 592 |
$upload_dir['url'] = $upload_dir['baseurl'].'/fv-player-youtube-channels'; |
| 593 |
return $upload_dir; |
| 594 |
} |
| 595 |
|
| 596 |
} |
| 597 |
|
| 598 |
function FV_Player_YouTube() { |
| 599 |
return FV_Player_YouTube::_get_instance(); |
| 600 |
} |
| 601 |
|
| 602 |
FV_Player_YouTube(); |
| 603 |
|