PluginProbe
FV Player 8 / 8.0.21
FV Player 8 v8.0.21
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.0.21, at controller/editor.php

1,016 lines 33.3 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 'src' => $video_src,
622 'splash' => $video_splash,
623 'title' => $video_title,
624 'splash_attachment_id' => $video_splash_attachment_id,
625 'timeline_previews' => $timeline_previews,
626 'hls_hlskey' => $hls_hlskey,
627 ) );
628 }
629 }
630
631 wp_send_json( array(
632 'error' => 'Nonce error: please reload your page'
633 ) );
634 }
635
636
637 add_action( 'wp_ajax_fv_player_guttenberg_attributes_save', 'fv_player_guttenberg_attributes_save' );
638
639 function fv_player_guttenberg_attributes_save() {
640 if( check_ajax_referer( "fv_player_gutenberg", "security" , false ) == 1 ) {
641 $player_id = intval($_POST['player_id']);
642 $splash_attachment_id = intval($_POST['splash_attachment_id']);
643 $src = sanitize_url($_POST['src']);
644 $splash = sanitize_url($_POST['splash']);
645 $title = sanitize_text_field($_POST['title']);
646 $timeline_previews = ! empty( $_POST['timeline_previews'] ) && strcmp( $_POST['timeline_previews'], 'false' ) !== 0 ? sanitize_url( trim( $_POST['timeline_previews'] ) ) : false;
647 $hls_hlskey = sanitize_text_field(trim($_POST['hls_hlskey']));
648
649 global $FV_Player_Db;
650
651 if( empty( $player_id) && empty($splash_attachment_id) && empty($src) && empty($splash) && empty($title) ) {
652 wp_send_json(array(
653 'info' => 'No data to save'
654 ));
655 }
656
657 // new player
658 if( !$player_id ) {
659 $meta = array();
660
661 if( !empty( $timeline_previews ) ) {
662 $meta[] = array(
663 'meta_key' => 'timeline_previews',
664 'meta_value' => $timeline_previews
665 );
666 }
667
668 if( !empty( $hls_hlskey ) && strcmp( $hls_hlskey, 'false' ) !== 0 ) {
669 $meta[] = array(
670 'meta_key' => 'hls_hlskey',
671 'meta_value' => $hls_hlskey
672 );
673 }
674
675 $player_id = $FV_Player_Db->import_player_data(false, false, array(
676 'date_created' => gmdate('Y-m-d H:i:s'),
677 'videos' => array(
678 array(
679 'src' => $src,
680 'splash' => $splash,
681 'title' => $title,
682 'splash_attachment_id' => $splash_attachment_id,
683 'meta' => $meta
684 ),
685 )
686 ));
687 } else { // existing player
688 $player = new FV_Player_Db_Player( $player_id );
689
690 if( $player && $player->getIsValid() ) {
691 $player_id = $player->getId();
692
693 foreach( $player->getVideos() AS $video ) {
694 $video->set( 'src', $src );
695 $video->set( 'splash', $splash );
696 $video->set( 'title', $title );
697 $video->set( 'splash_attachment_id', $splash_attachment_id );
698
699 // Make sure we do no loose video meta!
700 $video->save( array(), true );
701
702 if( empty($timeline_previews) || strcmp($timeline_previews, 'false') == 0 ) {
703 $video->deleteMetaValue( 'timeline_previews' );
704 } else {
705 $video->updateMetaValue( 'timeline_previews', $timeline_previews );
706 }
707
708 if( empty($hls_hlskey) || strcmp($hls_hlskey, 'false') == 0 ) {
709 $video->deleteMetaValue( 'hls_hlskey' );
710 } else {
711 $video->updateMetaValue( 'hls_hlskey', $hls_hlskey );
712 }
713
714 break; // only first video
715 }
716 }
717 }
718
719 if( $player_id ) {
720 wp_send_json( array(
721 'player_id' => $player_id,
722 'shortcodeContent' => '[fvplayer id="' . $player_id . '"]'
723 ) );
724 } else {
725 wp_send_json( array(
726 'error' => 'Error: Player not saved'
727 ) );
728 }
729
730 }
731
732 wp_send_json( array(
733 'error' => 'Nonce error: please reload your page'
734 ) );
735 }
736
737
738
739 function fv_player_editor_subtitle_fields() {
740 $subtitle_fields = apply_filters('fv_player_editor_subtitle_fields', array(
741 'subtitles' => array(
742 'items' => array(
743 array(
744 'label' => __( 'Subtitles', 'fv-player' ),
745 'label_signular' => __( 'Subtitle', 'fv-player' ),
746 'name' => 'subtitles',
747 'browser' => true,
748 'language' => true,
749 'type' => 'text',
750 'visible' => true,
751 'video_meta' => true,
752 )
753 ),
754 'sort' => false
755 )
756 ) );
757
758 return $subtitle_fields;
759 }
760
761
762
763
764 function fv_player_editor_video_fields() {
765 $fv_flowplayer_conf = get_option( 'fvwpflowplayer' );
766
767 $video_fields = apply_filters('fv_player_editor_video_fields', array(
768 'video' => array(
769 'items' => array(
770 array(
771 'label' => __( 'Video Link', 'fv-player' ),
772 'name' => 'src',
773 'browser' => true,
774 'type' => 'text',
775 'visible' => true
776 ),
777 array(
778 'name' => 'video_info',
779 'type' => 'notice_info',
780 'content' => '<ul></ul>',
781 ),
782 array(
783 'name' => 'auto_splash',
784 'type' => 'hidden',
785 ),
786 array(
787 'name' => 'auto_caption',
788 'type' => 'hidden',
789 ),
790 array(
791 'name' => 'encoding_job_id',
792 'type' => 'hidden'
793 ),
794 array(
795 'label' => __( 'Live Stream', 'fv-player' ),
796 'name' => 'live',
797 'children' => array(
798 array(
799 'label' => __( 'DVR Stream', 'fv-player' ),
800 'name' => 'dvr',
801 'video_meta' => true,
802 'visible' => true
803 ),
804 ),
805 ),
806 array(
807 'label' => __( 'Audio Stream', 'fv-player' ),
808 'name' => 'audio',
809 'video_meta' => true,
810 ),
811 array(
812 'label' => __( 'Advanced Settings', 'fv-player' ),
813 'name' => 'toggle_advanced_settings',
814 'visible' => true,
815 'children' => array(
816 array(
817 'label' => __( 'Mobile Video', 'fv-player' ),
818 'name' => 'mobile',
819 'browser' => true,
820 'type' => 'text',
821 'visible' => isset($fv_flowplayer_conf["interface"]["mobile"]) && $fv_flowplayer_conf["interface"]["mobile"] == 'true',
822 ),
823 array(
824 'label' => __( 'Alternative Format 1', 'fv-player' ),
825 'name' => 'src1',
826 'browser' => true,
827 'type' => 'text',
828 'visible' => true
829 ),
830 array(
831 'label' => __( 'Alternative Format 2', 'fv-player' ),
832 'name' => 'src2',
833 'browser' => true,
834 'type' => 'text',
835 'visible' => true
836 ),
837 array(
838 'label' => __( 'Remove Top and Bottom Black Bars', 'fv-player' ),
839 'name' => 'remove_black_bars',
840 'description' => __( 'Fixes video fit in mobile fullscreen when in landscape.', 'fv-player' ),
841 'video_meta' => true,
842 'visible' => true
843 ),
844 array(
845 'label' => __( 'RTMP', 'fv-player' ),
846 'name' => 'rtmp_show',
847 'no_data' => true,
848 'visible' => false,
849 'children' => array(
850 array(
851 'label' => __( 'Path', 'fv-player' ),
852 'name' => 'rtmp_path',
853 'type' => 'text',
854 'visible' => true
855 ),
856 array(
857 'label' => __( 'Server', 'fv-player' ),
858 'name' => 'rtmp',
859 'type' => 'text',
860 'visible' => true
861 ),
862 )
863 ),
864 ),
865 ),
866 array(
867 'label' => __( 'Splash Screen', 'fv-player' ),
868 'name' => 'splash',
869 'browser' => true,
870 'type' => 'text',
871 'visible' => true,
872 'description' => __( 'Will appear in place of the video before it plays.', 'fv-player' ),
873 ),
874 array(
875 'name' => 'splash_attachment_id',
876 'type' => 'hidden',
877 ),
878 array(
879 'label' => __( 'Title', 'fv-player' ),
880 'name' => 'title',
881 'type' => 'text',
882 'visible' => isset($fv_flowplayer_conf["interface"]["playlist_titles"]) && $fv_flowplayer_conf["interface"]["playlist_titles"] == 'true',
883 'description' => __( 'Will appear below the player and on playlist thumbnails. Also used for tracking.', 'fv-player' ),
884 'children' => array(
885 array(
886 'label' => __( 'Hide Title', 'fv-player' ),
887 'name' => 'title_hide',
888 'visible' => true,
889 // Only shows if Adanced Settings for video is on
890 'dependencies' => array( 'toggle_advanced_settings' => true ),
891 'description' => __( 'Use if you only want the title for tracking.', 'fv-player' ),
892 ),
893 ),
894 ),
895 array(
896 'label' => __( 'Splash Text', 'fv-player' ),
897 'name' => 'splash_text',
898 'type' => 'text',
899 'visible' => isset($fv_flowplayer_conf["interface"]["splash_text"]) && $fv_flowplayer_conf["interface"]["splash_text"] == 'true',
900 'description' => __( 'Will appear over the video before it plays.', 'fv-player' ),
901 ),
902 array(
903 'label' => __( 'Synopsis', 'fv-player' ),
904 'name' => 'synopsis',
905 'type' => 'textarea',
906 'visible' => isset($fv_flowplayer_conf["interface"]["synopsis"]) && $fv_flowplayer_conf["interface"]["synopsis"] == 'true',
907 'description' => __( 'Shows for the Vertical Season playlist style.', 'fv-player' ),
908 'video_meta' => true,
909 )
910 ),
911 'sort' => false
912 )
913 ) );
914
915 return $video_fields;
916 }
917
918
919
920
921 add_filter( 'save_post', 'fv_wp_flowplayer_convert_to_db', 9, 3 );
922
923 /**
924 * Convert shortcodes and links to DB on save
925 *
926 * @param int $post_id
927 * @param WP_Post $post
928 * @param bool $update
929 *
930 * @return void
931 */
932 function fv_wp_flowplayer_convert_to_db($post_id, $post, $update) {
933 global $wp, $wp_embed, $fv_fp, $FV_Player_Shortcode2Database_Conversion;
934
935 $is_classic_editor_save = !empty($_POST['action']) && sanitize_key( $_POST['action'] ) === 'editpost' && !empty($_POST['post_ID']) && absint( $_POST['post_ID'] ) == $post_id;
936 $is_gutenberg_post_save = !empty($wp->query_vars['rest_route']) && $wp->query_vars['rest_route'] == '/wp/v2/posts/'.$post_id;
937
938 if( !$is_classic_editor_save && !$is_gutenberg_post_save ) {
939 return;
940 }
941
942 // check if option is enabled
943 if( $fv_fp->_get_option('disable_convert_db_save') ) return;
944
945 // ignore revision
946 if ( wp_is_post_revision( $post_id ) ) return;
947
948 // ignore trash
949 if ( $post->post_status === 'trash' ) return;
950
951 $original_content = $post->post_content;
952 $new_content = $post->post_content;
953
954 // if( is_serialized($new_content) ) return; // TODO: is something serializing content?
955
956 // convert iframe/video tags to src shortcodes
957 $new_content = fv_player_handle_video_tags($new_content, false);
958 $new_content = fv_player_handle_youtube_links($new_content, false);
959 $new_content = fv_player_handle_vimeo_links($new_content, false);
960
961 $post->post_content = $new_content;
962
963 $FV_Player_Shortcode2Database_Conversion->set_live = true;
964
965 // convert src shortcodes to db
966 $new_content_data = $FV_Player_Shortcode2Database_Conversion->convert_one($post);
967 if( $new_content_data['content_updated'] ) {
968 $new_content = $new_content_data['new_content'];
969 }
970
971 // add gutenberg shortcode attributes
972 $new_content = preg_replace_callback(
973 array(
974 '~<!-- wp:paragraph -->\n<p>(\[fvplayer [\s\S]*?)<\/p>\n<!-- /wp:paragraph -->~',
975 '~<!-- wp:video .*? -->\n<figure class="wp-block-video">(\[fvplayer [\s\S]*?)<\/figure>\n<!-- /wp:video -->~',
976 ),
977 'fv_player_block_add_missing_attributes_callback',
978 $new_content
979 );
980
981 if ( strcmp( $original_content, $new_content ) != 0 ) {
982 add_filter(
983 'rest_prepare_' . $post->post_type,
984 function( $response, $post, $request ) {
985 $response->data['fv_player_reload'] = true;
986 return $response;
987 },
988 10,
989 3
990 );
991
992 // remove current action to prevent infinite loop when using wp_update_post
993 remove_action( 'save_post', 'fv_wp_flowplayer_convert_to_db', 9 );
994
995 // update post with updated content
996 wp_update_post( array( 'ID' => $post->ID, 'post_content' => $new_content ) );
997 }
998 }
999
1000
1001
1002
1003 /**
1004 * Elementor support
1005 */
1006 add_action( 'elementor/editor/wp_head', 'fv_player_shortcode_editor_scripts_enqueue' );
1007 add_action( 'elementor/editor/wp_head', 'fv_wp_flowplayer_edit_form_after_editor' );
1008 add_action( 'elementor/editor/wp_head', 'flowplayer_prepare_scripts' );
1009
1010 // Bring back the FV Player into Elementor Elements search - it's their "Hide native WordPress widgets from search results" setting
1011 add_filter( 'pre_option_elementor_experiment-e_hidden_wordpress_widgets', 'fv_player_editor_elementor_widget_search_enable' );
1012
1013 function fv_player_editor_elementor_widget_search_enable( $val ) {
1014 return 'inactive';
1015 }
1016