PluginProbe
FV Player 8 / 8.1
FV Player 8 v8.1
trunk 8.0.18 8.0.19 8.0.20 8.0.21 8.0.25 8.0.27 8.1 8.1.3
fv-player / controller / editor.php

editor.php in FV Player 8 8.1, at controller/editor.php

1,023 lines 33.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit;
5 }
6
7 add_action( 'admin_enqueue_scripts', 'fv_player_shortcode_editor_scripts' );
8
9 function fv_player_shortcode_editor_scripts( $page ) {
10 if( $page !== 'post.php' && $page !== 'post-new.php' && $page !== 'site-editor.php' && $page !== 'fv-player_page_fv_player_video_ads' && ( empty($_GET['page']) || sanitize_key( $_GET['page'] ) != 'fvplayer' && sanitize_key( $_GET['page'] ) != 'fv_player' ) ) {
11 return;
12 }
13
14 fv_player_shortcode_editor_scripts_enqueue();
15 }
16
17
18
19
20 function fv_player_shortcode_editor_scripts_enqueue( $extra_args = array() ) {
21 global $current_screen, $fv_wp_flowplayer_ver;
22
23 $url = flowplayer::get_plugin_url();
24
25 wp_enqueue_script('fv-player-editor-modal', $url.'/js/fv-player-editor-modal.js', array('jquery'), filemtime( dirname(__FILE__).'/../js/fv-player-editor-modal.js' ), true );
26
27 wp_enqueue_script('fvwpflowplayer-shortcode-editor', $url.'/js/shortcode-editor.js',array('jquery','jquery-ui-sortable'), filemtime( dirname(__FILE__).'/../js/shortcode-editor.js' ), true );
28 wp_enqueue_script('fv-player-editor-extras', $url.'/js/editor-extras.js',array('fvwpflowplayer-shortcode-editor'), filemtime( dirname(__FILE__).'/../js/editor-extras.js' ), true );
29 wp_enqueue_script('fvwpflowplayer-editor-screenshots', $url.'/js/editor-screenshots.js', array( 'fvwpflowplayer-shortcode-editor','flowplayer' ), filemtime( dirname(__FILE__).'/../js/editor-screenshots.js' ), true );
30
31 $fv_player_editor_conf = array(
32 'admin_url' => admin_url('admin.php?page=fv_player'),
33 'home_url' => home_url('/'),
34 'db_import_nonce' => wp_create_nonce( "fv-player-db-import" ),
35 'db_load_nonce' => wp_create_nonce( "fv-player-db-load" ),
36 'edit_nonce' => wp_create_nonce( "fv-player-edit" ),
37 'edit_posts_cell_nonce' => wp_create_nonce( "fv-player-edit_posts_cell_nonce" ),
38 // Used to create the select box with all the languages in JavaScript
39 'field_languages' => flowplayer::get_languages(),
40 'field_languages_default' => __( 'Pick language', 'fv_flowplayer' ),
41 'table_new_row_nonce' => wp_create_nonce( "fv-player-table_new_row_nonce" ),
42 'preview_nonce' => wp_create_nonce( "fv_player_preview" ),
43 'search_nonce' => wp_create_nonce( "fv-player-editor-search-nonce" ),
44 'splashscreen_nonce' => wp_create_nonce( "fv-player-splashscreen" ),
45 'shortcode_args_to_preserve' => array(
46 'ab',
47 'ad',
48 'ad_height',
49 'ad_width',
50 'autoplay',
51 'controlbar',
52 'embed',
53 'fullscreen',
54 'height',
55 'liststyle',
56 'logo',
57 'midroll',
58 'playlist_advance',
59 'playlist_hide',
60 'playlist_start',
61 'share',
62 'sort',
63 'vast',
64 'volume',
65 'width'
66 ),
67 'shortcode_args_not_db_compatible' => array(
68 'fullscreen',
69 'logo',
70 'playlist_advance',
71 'sort',
72 'volume'
73 ),
74 'have_fv_player_vimeo_live' => class_exists('FV_Player_Vimeo_Live_Stream'),
75 'is_fv_player_screen' => !empty($current_screen->id) && $current_screen->id == 'toplevel_page_fv_player',
76 'is_edit_posts_screen' => !empty($current_screen->base) && $current_screen->base == 'edit' && !empty($current_screen->post_type),
77 'keyup_throttle' => 500
78 );
79
80 // TODO: Ideally these inputs would not only be hidden, but they wouldn't save
81 if( !empty($extra_args['hide']) ) {
82 $extra_args['hide'] = explode( ',', $extra_args['hide'] );
83 }
84
85 foreach( array(
86 'field' => 'field_selector',
87 'frontend' => 'frontend',
88 'hide' => 'hide',
89 'library' => 'library', // TODO: Hide the Media Library buttons if the library is not found at all
90 'tabs' => 'tabs', // TODO: Ideally these inputs would not only be hidden, but they wouldn't save
91 ) AS $key => $setting ) {
92 if( !empty($extra_args[ $key ]) ) {
93 $fv_player_editor_conf[ $setting ] = $extra_args[ $key ];
94 }
95 }
96
97 wp_localize_script( 'fvwpflowplayer-shortcode-editor', 'fv_player_editor_conf', $fv_player_editor_conf );
98
99 wp_localize_script( 'fvwpflowplayer-shortcode-editor', 'fv_player_editor_translations', array(
100 'embed_notice' => __( 'Embed feature not supported in editor preview', 'fv-player' ),
101 'link_notice' => __( 'Link feature not supported in editor preview', 'fv-player' ),
102 'screenshot_cors_error' => __( 'Cannot obtain video screenshot, please make sure the video is served with <a href="https://foliovision.com/player/video-hosting/hls#hls-js">CORS headers</a>.', 'fv-player' ),
103 ) );
104
105 wp_localize_script( 'fvwpflowplayer-editor-screenshots', 'fv_player_editor_conf_screenshots', array(
106 'disable_domains' => apply_filters( 'fv_player_editor_screenshot_disable_domains', array() )
107 ) );
108
109 // TODO: Eliminate, keep the close button
110 wp_enqueue_style('fvwpflowplayer-domwindow-css', flowplayer::get_plugin_url().'/css/colorbox.css', '', $fv_wp_flowplayer_ver, 'screen');
111 wp_enqueue_style('fvwpflowplayer-shortcode-editor', flowplayer::get_plugin_url().'/css/shortcode-editor.css', '', filemtime( dirname(__FILE__).'/../css/shortcode-editor.css' ), 'screen');
112 }
113
114
115
116
117 add_action('media_buttons', 'flowplayer_add_media_button', 10);
118
119 function flowplayer_add_media_button() {
120 if(
121 stripos( sanitize_url( $_SERVER['REQUEST_URI'] ), 'post.php' ) !== FALSE ||
122 stripos( sanitize_url( $_SERVER['REQUEST_URI'] ), 'post-new.php' ) !== FALSE ||
123 isset($_POST['action']) && sanitize_key( $_POST['action'] ) == 'vc_edit_form'
124 ) {
125 echo '<a title="' . esc_attr__( 'Add FV Player', 'fv-player' ) . '" title="Insert a video" href="#" class="button fv-wordpress-flowplayer-button"><span></span> Player</a>';
126 }
127 }
128
129
130
131
132 add_action('media_upload_fvplayer_video', '__return_false'); // keep for compatibility!
133
134
135 add_action( 'enqueue_block_editor_assets', 'fv_wp_flowplayer_gutenberg_editor_load' );
136
137 function fv_wp_flowplayer_gutenberg_editor_load() {
138 add_action( 'admin_footer', 'fv_wp_flowplayer_edit_form_after_editor', 0 );
139
140 // if we are loading for Gutenberg, then forget about the load method for old editor
141 remove_action( 'edit_form_after_editor', 'fv_wp_flowplayer_edit_form_after_editor' );
142 }
143
144 add_action( 'edit_form_after_editor', 'fv_wp_flowplayer_edit_form_after_editor' );
145
146 function fv_wp_flowplayer_edit_form_after_editor( ) {
147 require_once dirname( __FILE__ ) . '/../view/wizard.php';
148
149 // todo: will some of this break page builders?
150 global $fv_fp_scripts, $fv_fp;
151 $fv_fp_scripts = array( 'fv_player_admin_load' => array( 'load' => true ) ); // without this or option js-everywhere the JS won't load
152 $fv_fp->load_hlsjs= true;
153 $fv_fp->load_dash = true;
154 $fv_fp->load_tabs = true;
155
156 if( !fv_player_extension_version_is_min('7.4.46.727','pro') ) {
157 global $FV_Player_Pro;
158 if( isset($FV_Player_Pro) && $FV_Player_Pro ) {
159 $FV_Player_Pro->bYoutube = true;
160 add_action('admin_footer', array( $FV_Player_Pro, 'styles' ) );
161 add_action('admin_footer', array( $FV_Player_Pro, 'scripts' ) );
162 }
163 }
164
165 if( !fv_player_extension_version_is_min('7.4.46.727','vast') ) {
166 global $FV_Player_VAST ;
167 if( isset($FV_Player_VAST ) && $FV_Player_VAST ) {
168 add_action('admin_footer', array( $FV_Player_VAST , 'func__wp_enqueue_scripts' ) );
169 }
170 }
171
172 if( !fv_player_extension_version_is_min('7.4.46.727','alternative-sources') ) {
173 global $FV_Player_Alternative_Sources ;
174 if( isset($FV_Player_Alternative_Sources ) && $FV_Player_Alternative_Sources ) {
175 add_action('admin_footer', array( $FV_Player_Alternative_Sources , 'enqueue_scripts' ) );
176 }
177 }
178
179 // Tell all the (modern) extensions to load frontend+backend assets
180 do_action('fv_player_extensions_admin_load_assets');
181
182 add_action('admin_footer','flowplayer_prepare_scripts');
183 }
184
185 // allow .vtt subtitle files
186 add_filter( 'wp_check_filetype_and_ext', 'fv_flowplayer_filetypes', 10, 4 );
187
188 function fv_flowplayer_filetypes( $aFile ) {
189 $aArgs = func_get_args();
190 foreach( array( 'vtt', 'webm', 'ogg') AS $item ) {
191 if( isset($aArgs[2]) && preg_match( '~\.'.$item.'~', $aArgs[2] ) ) {
192 $aFile['type'] = $item;
193 $aFile['ext'] = $item;
194 $aFile['proper_filename'] = $aArgs[2];
195 }
196 }
197 return $aFile;
198 }
199
200
201
202
203 add_filter('admin_print_scripts', 'flowplayer_print_scripts');
204
205 function flowplayer_print_scripts() {
206 wp_enqueue_script('media-upload');
207 wp_enqueue_script('thickbox');
208 }
209
210
211
212
213 add_action('admin_print_styles', 'flowplayer_print_styles');
214
215 function flowplayer_print_styles() {
216 wp_enqueue_style('thickbox');
217 }
218
219
220
221
222 add_action( 'save_post', 'fv_wp_flowplayer_save_post' );
223
224
225
226
227 add_action( 'save_post', 'fv_wp_flowplayer_featured_image' , 10000 );
228 add_action( 'fv_player_db_save', 'fv_wp_flowplayer_post_add_featured_image' );
229
230 function fv_wp_flowplayer_post_add_featured_image( $player_id ) {
231 global $FV_Player_Db;
232 $objPlayer = new FV_Player_Db_Player( $player_id, array(), $FV_Player_Db );
233 $posts = $objPlayer->getMetaValue('post_id'); // get posts where the player is embedded
234
235 if(empty($posts)) return; // no posts
236
237 foreach( $posts as $post_id ) {
238 $post_id = intval($post_id);
239 if( !has_post_thumbnail($post_id) ) {
240 fv_wp_flowplayer_featured_image($post_id);
241 }
242 }
243 }
244
245 // Set featured image from splash arg or splash_attachment_id or splash meta attribute
246 function fv_wp_flowplayer_featured_image($post_id) {
247 if( $parent_id = wp_is_post_revision($post_id) ) {
248 $post_id = $parent_id;
249 }
250
251 // thumbnail already set
252 $thumbnail_id = get_post_thumbnail_id($post_id);
253 if( $thumbnail_id != 0 ) {
254 return;
255 }
256
257 $post = get_post($post_id);
258
259 // Delete old meta
260 delete_post_meta($post_id, '_fv_player_featured_image_players');
261 delete_post_meta($post_id, '_fv_player_featured_image_splash_urls');
262
263 // We allow featured image to be set only once for each post
264 if( get_post_meta($post_id, '_fv_player_featured_image_set', true) ) {
265 return;
266 }
267
268 $thumbnail_id = false;
269 $splash_attachment_id = false;
270 $url = false;
271 $title = '';
272
273 // Search in post content
274 $search_context = $post->post_content;
275
276 // ...and also in post_meta
277 if( $aMetas = get_post_custom($post_id) ) { // parse [fvplayer id="..."] shortcode in post meta
278 foreach( $aMetas AS $aMeta ) {
279 foreach( $aMeta AS $meta_value ) {
280 if ( is_string( $meta_value ) && preg_match_all( '/\[fvplayer.*?\]/', $meta_value, $shortcodes ) ) {
281 foreach( $shortcodes[0] AS $shortcode ) {
282 $search_context .= "\n\n".$shortcode;
283 }
284 }
285 }
286 }
287 }
288
289 if( preg_match_all('/(?:splash=\\\?")([^"]*.(?:jpg|gif|png))/', $search_context, $splash_images) ) { // parse splash="..." in post content
290 foreach($splash_images[1] as $src ) {
291 if( !empty($src) ) {
292 $url = $src;
293 break;
294 }
295 }
296 }
297
298 if( !$url && preg_match_all('/\[fvplayer.*?id="(\d+)/', $search_context, $ids) ) { // parse [fvplayer id="..."] shortcode in post content
299 global $FV_Player_Db;
300
301 foreach( $ids[1] as $player_id ) {
302 $atts = $FV_Player_Db->getPlayerAttsFromDb( array( 'id' => $player_id ) );
303
304 if( !empty($atts['title']) ) {
305 $title = $atts['title'];
306 }
307
308 if( !empty($atts['splash_attachment_id']) ) { // first check splash_attachment_id
309 $splash_attachment_id = (int) $atts['splash_attachment_id'];
310
311 } else if( !empty($atts['splash']) ) { // fallback to splash
312 $url = $atts['splash'];
313 }
314
315 // If we found splash attachmend ID or URL remember that this player has set the Featured Image
316 if($splash_attachment_id || $url) {
317 break;
318 }
319 }
320 }
321
322 if( $splash_attachment_id ) {
323 $thumbnail_id = $splash_attachment_id; // use saved splash
324 } else if($url) {
325 $args = array( // check if splash was already downloaded
326 'post_type' => 'attachment',
327 'meta_query' => array(
328 array(
329 'key' => '_fv_player_splash_image_url',
330 'value' => $url,
331 )
332 )
333 );
334
335 $posts = get_posts( $args );
336
337 if( !empty($posts[0]->ID) ) {
338 $thumbnail_id = $posts[0]->ID;
339 } else {
340 $thumbnail_id = fv_wp_flowplayer_save_to_media_library($url, $post_id, $title); // download splash
341
342 if ( is_wp_error( $thumbnail_id ) ) {
343 return;
344 }
345
346 if($thumbnail_id) {
347 update_post_meta( $thumbnail_id, '_fv_player_splash_image_url', $url );
348 }
349 }
350 }
351
352 if( $thumbnail_id ) { // set post thumbnail if we have thumbnail id
353 update_post_meta($post_id, '_fv_player_featured_image_set', $thumbnail_id);
354 set_post_thumbnail( $post_id, $thumbnail_id );
355 }
356 }
357
358 function fv_wp_flowplayer_construct_filename( $post_id ) {
359 $filename = get_the_title( $post_id );
360 $filename = sanitize_title( $filename, $post_id );
361 $filename = urldecode( $filename );
362 $filename = preg_replace( '/[^a-zA-Z0-9\-]/', '', $filename );
363 $filename = substr( $filename, 0, 32 );
364 $filename = trim( $filename, '-' );
365 if ( $filename == '' ) $filename = (string) $post_id;
366 return $filename;
367 }
368
369 function fv_wp_flowplayer_save_to_media_library( $image_url, $post_id, $title = false ) {
370
371 $image_url = apply_filters( 'fv_flowplayer_splash', $image_url );
372
373 $error = '';
374 $response = wp_remote_get( $image_url );
375 if( is_wp_error( $response ) ) {
376 $error = new WP_Error(
377 'thumbnail_retrieval',
378 sprintf( __( 'Error retrieving a thumbnail from the URL <a href="%1$s">%1$s</a> using <code>wp_remote_get()</code><br />If opening that URL in your web browser returns anything else than an error page, the problem may be related to your web server and might be something your host administrator can solve.', 'video-thumbnails' ), $image_url ) . '<br>' . esc_html__( 'Error Details:', 'video-thumbnails' ) . ' ' . $response->get_error_message()
379 );
380 } else {
381 $image_contents = $response['body'];
382 $image_type = wp_remote_retrieve_header( $response, 'content-type' );
383 }
384
385 if ( $error != '' || $image_contents == '' ) {
386 return false;
387 } else {
388
389 // Translate MIME type into an extension
390 if ( $image_type == 'image/jpeg' ) {
391 $image_extension = '.jpg';
392 } elseif ( $image_type == 'image/png' ) {
393 $image_extension = '.png';
394 } elseif ( $image_type == 'image/gif' ) {
395 $image_extension = '.gif';
396 } else {
397 return new WP_Error( 'thumbnail_upload', __( 'Unsupported MIME type:', 'video-thumbnails' ) . ' ' . $image_type );
398 }
399
400 // Construct a file name with extension
401 if( $title ) {
402 $new_filename = sanitize_file_name($title);
403 } else {
404 $new_filename = fv_wp_flowplayer_construct_filename( $post_id ) . $image_extension;
405 }
406
407 // Save the image bits using the new filename
408 $upload = wp_upload_bits( $new_filename, null, $image_contents );
409
410 // Stop for any errors while saving the data or else continue adding the image to the media library
411 if ( $upload['error'] ) {
412 $error = new WP_Error( 'thumbnail_upload', __( 'Error uploading image data:', 'video-thumbnails' ) . ' ' . $upload['error'] );
413 return $error;
414 } else {
415
416 $wp_filetype = wp_check_filetype( basename( $upload['file'] ), null );
417
418 $upload = apply_filters( 'wp_handle_upload', array(
419 'file' => $upload['file'],
420 'url' => $upload['url'],
421 'type' => $wp_filetype['type']
422 ), 'sideload' );
423
424 // Contstruct the attachment array
425 $attachment = array(
426 'post_mime_type' => $upload['type'],
427 'post_title' => get_the_title( $post_id ),
428 'post_content' => '',
429 'post_status' => 'inherit'
430 );
431 // Insert the attachment
432 $attach_id = wp_insert_attachment( $attachment, $upload['file'], $post_id );
433
434 require_once(ABSPATH . 'wp-admin/includes/image.php');
435
436 // Define attachment metadata
437 $attach_data = wp_generate_attachment_metadata( $attach_id, $upload['file'] );
438
439 // Assign metadata to attachment
440 wp_update_attachment_metadata( $attach_id, $attach_data );
441
442 }
443
444 }
445
446 return $attach_id;
447
448 }
449
450 add_action( 'wp_ajax_fv_player_splashcreen_action', 'fv_player_splashcreen_action' );
451
452 function fv_player_splashcreen_action() {
453
454 global $wpdb; //access to the database
455 $jsonReturn = '';
456
457 function fv_player_splashcreen_getTitleFromUrl($url) {
458 $arr = explode('/', $url);
459 $title = end($arr);
460
461 if( strpos($title, ".m3u8") !== false ) {
462 unset($arr[count($arr)-1]);
463 $title = end($arr);
464 }
465
466 // Remove file extension from $title
467 $title = preg_replace('/\.[^.]+$/', '', $title);
468
469 $vid_replacements = array(
470 'watch?v=' => 'YouTube: '
471 );
472 $title = str_replace(array_keys($vid_replacements), array_values($vid_replacements), $title);
473
474 if( is_numeric($title) && intval($title) == $title && stripos($url,'vimeo.com/') !== false ) {
475 $title = "Vimeo: ".$title;
476 }
477 return urldecode($title);
478 }
479
480 if( check_ajax_referer( "fv-player-splashscreen", "security" , false ) == 1 ) {
481 $title = sanitize_text_field( $_POST['title'] );
482 $img = sanitize_text_field( $_POST['img'] );
483 $limit = 128 - 5; // .jpeg
484
485 $img = str_replace('data:image/jpeg;base64,', '', $img);
486 $img = str_replace(' ', '+', $img);
487
488 $title = fv_player_splashcreen_getTitleFromUrl($title);
489 $title = sanitize_title($title);
490
491 if( function_exists('mb_strinwidth') ) {
492 $title = mb_strimwidth($title, 0, $limit, '', 'UTF-8');
493 } else if( strlen( $title ) > $limit ) {
494 $title = substr($title, 0, $limit);
495 }
496
497 $decoded = base64_decode($img);
498
499 $upload_dir = wp_upload_dir();
500 $upload_path = str_replace( '/', DIRECTORY_SEPARATOR, $upload_dir['path'] ) . DIRECTORY_SEPARATOR;
501
502 $filename = $title .'.jpg';
503
504 // $hashed_filename = md5( $filename . microtime() ) . '_' . $filename;
505
506 global $wp_filesystem;
507 $wp_filesystem->put_contents( $upload_path . $filename, $decoded );
508
509 // Handle upload file
510 if( !function_exists( 'wp_handle_sideload' ) ) {
511 require_once( ABSPATH . 'wp-admin/includes/file.php' );
512 }
513
514 // Debug error
515 if( !function_exists( 'wp_get_current_user' ) ) {
516 require_once( ABSPATH . 'wp-includes/pluggable.php' );
517 }
518
519 // New file
520 $file = array();
521 $file['error'] = '';
522 $file['tmp_name'] = $upload_path . $filename;
523 $file['name'] = $filename;
524 $file['type'] = 'image/jpeg';
525 $file['size'] = filesize( $upload_path . $filename );
526
527 $file_return = wp_handle_sideload( $file, array( 'test_form' => false ) );
528
529 if ( ! empty( $file_return['error'] ) ) {
530 $jsonReturn = array(
531 'src' => '',
532 'error' => $file_return['error']
533 );
534 } else {
535 $filename = $file_return['file'];
536
537 $attachment = array(
538 'post_mime_type' => $file_return['type'],
539 'post_title' => preg_replace('/\.[^.]+$/', '', basename($filename)),
540 'post_content' => '',
541 'post_status' => 'inherit',
542 'guid' => $upload_dir['url'] . '/' . basename($filename)
543 );
544
545 $attach_id = wp_insert_attachment( $attachment, $filename, 0, true );
546
547 if( is_wp_error( $attach_id ) ) {
548 $jsonReturn = array(
549 'src' => '',
550 'error' => $attach_id->get_error_message()
551 );
552 } else {
553 require_once(ABSPATH . 'wp-admin/includes/image.php');
554
555 $attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
556 wp_update_attachment_metadata( $attach_id, $attach_data );
557
558 $src = wp_get_attachment_image_url($attach_id, $size = 'full', false);
559
560 $jsonReturn = array(
561 'src' => $src,
562 'error' => ''
563 );
564 }
565 }
566 } else {
567 $jsonReturn = array(
568 'src' => '',
569 'error' => 'Nonce error - please reload your page'
570 );
571 }
572
573 header('Content-Type: application/json');
574 echo wp_json_encode($jsonReturn);
575
576 wp_die();
577 }
578
579 add_action( 'wp_ajax_fv_player_guttenberg_attributes_load', 'fv_player_guttenberg_attributes_load' );
580
581 function fv_player_guttenberg_attributes_load() {
582 if( check_ajax_referer( "fv_player_gutenberg", "security" , false ) == 1 ) {
583 $player_id = intval($_POST['player_id']);
584
585 if( empty( $player_id ) ) {
586 wp_send_json(array(
587 'info' => 'No player ID'
588 ));
589 }
590
591 $player = new FV_Player_Db_Player( $player_id );
592
593 if( $player && $player->getIsValid() ) {
594 $player_id = $player->getId();
595 $video_src = '';
596 $video_splash = '';
597 $video_title = '';
598 $video_splash_attachment_id = '';
599 $timeline_previews = '';
600 $hls_hlskey = '';
601
602 foreach( $player->getVideos() AS $video ) {
603 $video_src = $video->getSrc();
604 $video_splash = $video->getSplash();
605 $video_title = $video->getTitle();
606 $video_splash_attachment_id = $video->getSplashAttachmentId();
607 $timeline_previews = $video->getMetaValue('timeline_previews', true) ? $video->getMetaValue('timeline_previews', true) : '';
608 $hls_hlskey = $video->getMetaValue('hls_hlskey', true) ? $video->getMetaValue('hls_hlskey', true) : '';
609 break; // only first video
610 }
611
612 if( strcmp($timeline_previews, 'false') == 0 ) {
613 $timeline_previews = '';
614 }
615
616 if( strcmp($hls_hlskey, 'false') == 0 ) {
617 $hls_hlskey = '';
618 }
619
620 wp_send_json( array(
621 'shortcodeContent' => '[fvplayer id="' . $player_id . '"]',
622 'src' => $video_src,
623 'splash' => $video_splash,
624 'title' => $video_title,
625 'splash_attachment_id' => $video_splash_attachment_id,
626 'timeline_previews' => $timeline_previews,
627 'hls_hlskey' => $hls_hlskey,
628 ) );
629 }
630 }
631
632 wp_send_json( array(
633 'error' => 'Nonce error: please reload your page'
634 ) );
635 }
636
637
638 add_action( 'wp_ajax_fv_player_guttenberg_attributes_save', 'fv_player_guttenberg_attributes_save' );
639
640 function fv_player_guttenberg_attributes_save() {
641 if( check_ajax_referer( "fv_player_gutenberg", "security" , false ) == 1 ) {
642 $player_id = intval($_POST['player_id']);
643 $splash_attachment_id = intval($_POST['splash_attachment_id']);
644 $src = sanitize_url($_POST['src']);
645 $splash = sanitize_url($_POST['splash']);
646 $title = sanitize_text_field($_POST['title']);
647 $timeline_previews = ! empty( $_POST['timeline_previews'] ) && strcmp( $_POST['timeline_previews'], 'false' ) !== 0 ? sanitize_url( trim( $_POST['timeline_previews'] ) ) : false;
648 $hls_hlskey = sanitize_text_field(trim($_POST['hls_hlskey']));
649
650 global $FV_Player_Db;
651
652 if( empty( $player_id) && empty($splash_attachment_id) && empty($src) && empty($splash) && empty($title) ) {
653 wp_send_json(array(
654 'info' => 'No data to save'
655 ));
656 }
657
658 // new player
659 if( !$player_id ) {
660 $meta = array();
661
662 if( !empty( $timeline_previews ) ) {
663 $meta[] = array(
664 'meta_key' => 'timeline_previews',
665 'meta_value' => $timeline_previews
666 );
667 }
668
669 if( !empty( $hls_hlskey ) && strcmp( $hls_hlskey, 'false' ) !== 0 ) {
670 $meta[] = array(
671 'meta_key' => 'hls_hlskey',
672 'meta_value' => $hls_hlskey
673 );
674 }
675
676 $player_id = $FV_Player_Db->import_player_data(false, false, array(
677 'date_created' => gmdate('Y-m-d H:i:s'),
678 'videos' => array(
679 array(
680 'src' => $src,
681 'splash' => $splash,
682 'title' => $title,
683 'splash_attachment_id' => $splash_attachment_id,
684 'meta' => $meta
685 ),
686 )
687 ));
688 } else { // existing player
689 $player = new FV_Player_Db_Player( $player_id );
690
691 if( $player && $player->getIsValid() ) {
692 $player_id = $player->getId();
693
694 foreach( $player->getVideos() AS $video ) {
695 $video->set( 'src', $src );
696 $video->set( 'splash', $splash );
697 $video->set( 'title', $title );
698 $video->set( 'splash_attachment_id', $splash_attachment_id );
699
700 // Make sure we do no loose video meta!
701 $video->save( array(), true );
702
703 if( empty($timeline_previews) || strcmp($timeline_previews, 'false') == 0 ) {
704 $video->deleteMetaValue( 'timeline_previews' );
705 } else {
706 $video->updateMetaValue( 'timeline_previews', $timeline_previews );
707 }
708
709 if( empty($hls_hlskey) || strcmp($hls_hlskey, 'false') == 0 ) {
710 $video->deleteMetaValue( 'hls_hlskey' );
711 } else {
712 $video->updateMetaValue( 'hls_hlskey', $hls_hlskey );
713 }
714
715 break; // only first video
716 }
717 }
718 }
719
720 if( $player_id ) {
721
722 // Load video data again to get the updated values, used for Elementor Widget
723 $player = new FV_Player_Db_Player( $player_id );
724 if ( $player && $player->getIsValid() ) {
725 $videos = $player->getVideos();
726 if ( $videos ) {
727 foreach ( $videos as $video ) {
728 $splash = $video->getSplash();
729 $title = $video->getTitle();
730 $splash_attachment_id = $video->getSplashAttachmentId();
731 $timeline_previews = $video->getMetaValue('timeline_previews', true) ? $video->getMetaValue('timeline_previews', true) : '';
732 $hls_hlskey = $video->getMetaValue('hls_hlskey', true) ? $video->getMetaValue('hls_hlskey', true) : '';
733 break; // only first video
734 }
735 }
736 }
737
738 wp_send_json( array(
739 'player_id' => $player_id,
740 'shortcodeContent' => '[fvplayer id="' . $player_id . '"]',
741 'src' => $src,
742 'splash' => $splash,
743 'title' => $title,
744 'splash_attachment_id' => $splash_attachment_id,
745 'timeline_previews' => $timeline_previews,
746 'hls_hlskey' => $hls_hlskey
747 ) );
748 } else {
749 wp_send_json( array(
750 'error' => 'Error: Player not saved'
751 ) );
752 }
753
754 }
755
756 wp_send_json( array(
757 'error' => 'Nonce error: please reload your page'
758 ) );
759 }
760
761
762
763 function fv_player_editor_subtitle_fields() {
764 $subtitle_fields = apply_filters('fv_player_editor_subtitle_fields', array(
765 'subtitles' => array(
766 'items' => array(
767 array(
768 'label' => __( 'Subtitles', 'fv-player' ),
769 'label_signular' => __( 'Subtitle', 'fv-player' ),
770 'name' => 'subtitles',
771 'browser' => true,
772 'language' => true,
773 'type' => 'text',
774 'visible' => true,
775 'video_meta' => true,
776 )
777 ),
778 'sort' => false
779 )
780 ) );
781
782 return $subtitle_fields;
783 }
784
785
786
787
788 function fv_player_editor_video_fields() {
789 $fv_flowplayer_conf = get_option( 'fvwpflowplayer' );
790
791 $video_fields = apply_filters('fv_player_editor_video_fields', array(
792 'video' => array(
793 'items' => array(
794 array(
795 'label' => __( 'Video Link', 'fv-player' ),
796 'name' => 'src',
797 'browser' => true,
798 'type' => 'text',
799 'visible' => true
800 ),
801 array(
802 'name' => 'video_info',
803 'type' => 'notice_info',
804 'content' => '<ul></ul>',
805 ),
806 array(
807 'name' => 'auto_splash',
808 'type' => 'hidden',
809 ),
810 array(
811 'name' => 'auto_caption',
812 'type' => 'hidden',
813 ),
814 array(
815 'name' => 'encoding_job_id',
816 'type' => 'hidden'
817 ),
818 array(
819 'label' => __( 'Live Stream', 'fv-player' ),
820 'name' => 'live',
821 'children' => array(
822 array(
823 'label' => __( 'DVR Stream', 'fv-player' ),
824 'name' => 'dvr',
825 'video_meta' => true,
826 'visible' => true
827 ),
828 ),
829 ),
830 array(
831 'label' => __( 'Audio Stream', 'fv-player' ),
832 'name' => 'audio',
833 'video_meta' => true,
834 ),
835 array(
836 'label' => __( 'Advanced Settings', 'fv-player' ),
837 'name' => 'toggle_advanced_settings',
838 'visible' => true,
839 'children' => array(
840 array(
841 'label' => __( 'Mobile Video', 'fv-player' ),
842 'name' => 'mobile',
843 'browser' => true,
844 'type' => 'text',
845 'visible' => isset($fv_flowplayer_conf["interface"]["mobile"]) && $fv_flowplayer_conf["interface"]["mobile"] == 'true',
846 ),
847 array(
848 'label' => __( 'Alternative Format 1', 'fv-player' ),
849 'name' => 'src1',
850 'browser' => true,
851 'type' => 'text',
852 'visible' => true
853 ),
854 array(
855 'label' => __( 'Alternative Format 2', 'fv-player' ),
856 'name' => 'src2',
857 'browser' => true,
858 'type' => 'text',
859 'visible' => true
860 ),
861 array(
862 'label' => __( 'Remove Top and Bottom Black Bars', 'fv-player' ),
863 'name' => 'remove_black_bars',
864 'description' => __( 'Fixes video fit in mobile fullscreen when in landscape.', 'fv-player' ),
865 'video_meta' => true,
866 'visible' => true
867 ),
868 array(
869 'label' => __( 'RTMP', 'fv-player' ),
870 'name' => 'rtmp_show',
871 'no_data' => true,
872 'visible' => false,
873 'children' => array(
874 array(
875 'label' => __( 'Path', 'fv-player' ),
876 'name' => 'rtmp_path',
877 'type' => 'text',
878 'visible' => true
879 ),
880 array(
881 'label' => __( 'Server', 'fv-player' ),
882 'name' => 'rtmp',
883 'type' => 'text',
884 'visible' => true
885 ),
886 )
887 ),
888 ),
889 ),
890 array(
891 'label' => __( 'Splash Screen', 'fv-player' ),
892 'name' => 'splash',
893 'browser' => true,
894 'type' => 'text',
895 'visible' => true,
896 'description' => __( 'Will appear in place of the video before it plays.', 'fv-player' ),
897 ),
898 array(
899 'name' => 'splash_attachment_id',
900 'type' => 'hidden',
901 ),
902 array(
903 'label' => __( 'Title', 'fv-player' ),
904 'name' => 'title',
905 'type' => 'text',
906 'visible' => isset($fv_flowplayer_conf["interface"]["playlist_titles"]) && $fv_flowplayer_conf["interface"]["playlist_titles"] == 'true',
907 'description' => __( 'Will appear below the player and on playlist thumbnails. Also used for tracking.', 'fv-player' ),
908 'children' => array(
909 array(
910 'label' => __( 'Hide Title', 'fv-player' ),
911 'name' => 'title_hide',
912 'visible' => true,
913 // Only shows if Adanced Settings for video is on
914 'dependencies' => array( 'toggle_advanced_settings' => true ),
915 'description' => __( 'Use if you only want the title for tracking.', 'fv-player' ),
916 ),
917 ),
918 ),
919 array(
920 'label' => __( 'Splash Text', 'fv-player' ),
921 'name' => 'splash_text',
922 'type' => 'text',
923 'visible' => isset($fv_flowplayer_conf["interface"]["splash_text"]) && $fv_flowplayer_conf["interface"]["splash_text"] == 'true',
924 'description' => __( 'Will appear over the video before it plays.', 'fv-player' ),
925 ),
926 array(
927 'label' => __( 'Synopsis', 'fv-player' ),
928 'name' => 'synopsis',
929 'type' => 'textarea',
930 'visible' => isset($fv_flowplayer_conf["interface"]["synopsis"]) && $fv_flowplayer_conf["interface"]["synopsis"] == 'true',
931 'description' => __( 'Shows for the Vertical Season playlist style.', 'fv-player' ),
932 'video_meta' => true,
933 )
934 ),
935 'sort' => false
936 )
937 ) );
938
939 return $video_fields;
940 }
941
942
943
944
945 add_filter( 'save_post', 'fv_wp_flowplayer_convert_to_db', 9, 3 );
946
947 /**
948 * Convert shortcodes and links to DB on save
949 *
950 * @param int $post_id
951 * @param WP_Post $post
952 * @param bool $update
953 *
954 * @return void
955 */
956 function fv_wp_flowplayer_convert_to_db($post_id, $post, $update) {
957 global $wp, $wp_embed, $fv_fp, $FV_Player_Shortcode2Database_Conversion;
958
959 $is_classic_editor_save = !empty($_POST['action']) && sanitize_key( $_POST['action'] ) === 'editpost' && !empty($_POST['post_ID']) && absint( $_POST['post_ID'] ) == $post_id;
960 $is_gutenberg_post_save = !empty($wp->query_vars['rest_route']) && $wp->query_vars['rest_route'] == '/wp/v2/posts/'.$post_id;
961
962 if( !$is_classic_editor_save && !$is_gutenberg_post_save ) {
963 return;
964 }
965
966 // check if option is enabled
967 if( $fv_fp->_get_option('disable_convert_db_save') ) return;
968
969 // ignore revision
970 if ( wp_is_post_revision( $post_id ) ) return;
971
972 // ignore trash
973 if ( $post->post_status === 'trash' ) return;
974
975 $original_content = $post->post_content;
976 $new_content = $post->post_content;
977
978 // if( is_serialized($new_content) ) return; // TODO: is something serializing content?
979
980 // convert iframe/video tags to src shortcodes
981 $new_content = fv_player_handle_video_tags($new_content, false);
982 $new_content = fv_player_handle_youtube_links($new_content, false);
983 $new_content = fv_player_handle_vimeo_links($new_content, false);
984
985 $post->post_content = $new_content;
986
987 $FV_Player_Shortcode2Database_Conversion->set_live = true;
988
989 // convert src shortcodes to db
990 $new_content_data = $FV_Player_Shortcode2Database_Conversion->convert_one($post);
991 if( $new_content_data['content_updated'] ) {
992 $new_content = $new_content_data['new_content'];
993 }
994
995 // add gutenberg shortcode attributes
996 $new_content = preg_replace_callback(
997 array(
998 '~<!-- wp:paragraph -->\n<p>(\[fvplayer [\s\S]*?)<\/p>\n<!-- /wp:paragraph -->~',
999 '~<!-- wp:video .*? -->\n<figure class="wp-block-video">(\[fvplayer [\s\S]*?)<\/figure>\n<!-- /wp:video -->~',
1000 ),
1001 'fv_player_block_add_missing_attributes_callback',
1002 $new_content
1003 );
1004
1005 if ( strcmp( $original_content, $new_content ) != 0 ) {
1006 add_filter(
1007 'rest_prepare_' . $post->post_type,
1008 function( $response, $post, $request ) {
1009 $response->data['fv_player_reload'] = true;
1010 return $response;
1011 },
1012 10,
1013 3
1014 );
1015
1016 // remove current action to prevent infinite loop when using wp_update_post
1017 remove_action( 'save_post', 'fv_wp_flowplayer_convert_to_db', 9 );
1018
1019 // update post with updated content
1020 wp_update_post( array( 'ID' => $post->ID, 'post_content' => $new_content ) );
1021 }
1022 }
1023