文件操作 - video.php
返回文件管理
返回主菜单
删除本文件
文件: /storage/v12552/stanleysteamer/public_html/wp-content/themes/bricks/includes/elements/video.php
编辑文件内容
<?php namespace Bricks; if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly class Element_Video extends Element { public $block = [ 'core/video', 'core-embed/youtube', 'core-embed/vimeo' ]; public $category = 'basic'; public $name = 'video'; public $icon = 'ti-video-clapper'; public $scripts = [ 'bricksVideo' ]; public $draggable = false; public function get_label() { return esc_html__( 'Video', 'bricks' ); } public function enqueue_scripts() { if ( isset( $this->theme_styles['customPlayer'] ) ) { if ( ! Database::get_setting( 'disableBricksCascadeLayer' ) ) { // @since 2.0 wp_enqueue_style( 'video-plyr', BRICKS_URL_ASSETS . 'css/libs/plyr-layer.min.css', [], '3.7.8' ); } else { wp_enqueue_style( 'video-plyr', BRICKS_URL_ASSETS . 'css/libs/plyr.min.css', [], '3.7.8' ); } wp_enqueue_script( 'video-plyr', BRICKS_URL_ASSETS . 'js/libs/plyr.min.js', [ 'bricks-scripts' ], '3.7.8', true ); } } public function set_control_groups() { $this->control_groups['icon'] = [ 'title' => esc_html__( 'Overlay', 'bricks' ) . ' / ' . esc_html__( 'Icon', 'bricks' ), 'tab' => 'content', ]; } public function set_controls() { $this->controls['videoType'] = [ 'tab' => 'content', 'label' => esc_html__( 'Source', 'bricks' ), 'type' => 'select', 'options' => [ 'youtube' => 'YouTube', 'vimeo' => 'Vimeo', 'media' => esc_html__( 'Media', 'bricks' ), 'file' => esc_html__( 'File URL', 'bricks' ), 'meta' => esc_html__( 'Dynamic Data', 'bricks' ), ], 'default' => 'youtube', 'inline' => true, 'clearable' => false, ]; // @since 1.6.1 $this->controls['iframeTitle'] = [ 'tab' => 'content', 'label' => esc_html__( 'Iframe title', 'bricks' ), 'type' => 'text', 'inline' => true, 'required' => [ 'videoType', '=', [ 'youtube', 'vimeo' ] ], ]; // @since 2.2 $this->controls['aspectRatio'] = [ 'tab' => 'content', 'label' => esc_html__( 'Aspect ratio', 'bricks' ), 'type' => 'select', 'options' => [ '16/9' => '16:9 (' . esc_html__( 'Landscape', 'bricks' ) . ')', '9/16' => '9:16 (' . esc_html__( 'Portrait', 'bricks' ) . '/' . esc_html__( 'Shorts', 'bricks' ) . ')', '4/3' => '4:3 (' . esc_html__( 'Standard', 'bricks' ) . ')', '3/4' => '3:4 (' . esc_html__( 'Portrait', 'bricks' ) . ')', '21/9' => '21:9 (' . esc_html__( 'Ultrawide', 'bricks' ) . ')', '1/1' => '1:1 (' . esc_html__( 'Square', 'bricks' ) . ')', '2/3' => '2:3 (' . esc_html__( 'Portrait', 'bricks' ) . ')', '3/2' => '3:2 (' . esc_html__( 'Landscape', 'bricks' ) . ')', ], 'inline' => true, 'placeholder' => '16:9', 'css' => [ [ 'property' => 'aspect-ratio', ], ], ]; // @since 2.3 $this->controls['objectFit'] = [ 'tab' => 'content', 'label' => esc_html__( 'Object fit', 'bricks' ), 'type' => 'select', 'options' => $this->control_options['objectFit'], 'inline' => true, 'css' => [ [ 'property' => 'object-fit', 'selector' => 'video', ], ], 'required' => [ 'videoType', '=', [ 'media', 'file', 'meta' ] ], ]; /** * Type: YouTube */ $this->controls['youTubeId'] = [ 'tab' => 'content', 'label' => esc_html__( 'YouTube video ID/URL', 'bricks' ), 'type' => 'text', 'inline' => false, 'required' => [ 'videoType', '=', 'youtube' ], 'default' => '5DGo0AYOJ7s', ]; // Cannot be used if using preview image $this->controls['youtubeAutoplay'] = [ 'tab' => 'content', 'label' => esc_html__( 'Autoplay', 'bricks' ), 'type' => 'checkbox', 'info' => 'YouTube: ' . esc_html__( 'Not supported on mobile devices', 'bricks' ), 'required' => [ [ 'videoType', '=', 'youtube' ], [ 'previewImage' , '!=', true ], ], ]; $this->controls['youtubeControls'] = [ 'tab' => 'content', 'label' => esc_html__( 'Controls', 'bricks' ), 'type' => 'checkbox', 'default' => true, 'required' => [ 'videoType', '=', 'youtube' ], ]; $this->controls['youtubeLoop'] = [ 'tab' => 'content', 'label' => esc_html__( 'Loop', 'bricks' ), 'type' => 'checkbox', 'required' => [ 'videoType', '=', 'youtube' ], ]; $this->controls['youtubeMute'] = [ 'tab' => 'content', 'label' => esc_html__( 'Mute', 'bricks' ), 'type' => 'checkbox', 'required' => [ 'videoType', '=', 'youtube' ], ]; $this->controls['youtubeRel'] = [ 'tab' => 'content', 'label' => esc_html__( 'Related videos from other channels', 'bricks' ), 'type' => 'checkbox', 'required' => [ 'videoType', '=', 'youtube' ], ]; $this->controls['youtubeDoNotTrack'] = [ 'tab' => 'content', 'label' => esc_html__( 'Do not track', 'bricks' ), 'type' => 'checkbox', 'required' => [ 'videoType', '=', 'youtube' ], ]; $this->controls['youtubeStart'] = [ 'tab' => 'content', 'label' => esc_html__( 'Start time [s]', 'bricks' ), 'type' => 'number', 'placeholder' => esc_html__( 'Seconds', 'bricks' ), 'inline' => true, 'hasDynamicData' => true, 'required' => [ 'videoType', '=', 'youtube' ], ]; $this->controls['youtubeEnd'] = [ 'tab' => 'content', 'label' => esc_html__( 'End time [s]', 'bricks' ), 'type' => 'number', 'placeholder' => esc_html__( 'Seconds', 'bricks' ), 'inline' => true, 'hasDynamicData' => true, 'required' => [ 'videoType', '=', 'youtube' ], ]; $this->controls['youtubeDisableFullscreenButton'] = [ 'tab' => 'content', 'label' => esc_html__( 'Disable fullscreen button', 'bricks' ), 'type' => 'checkbox', 'default' => true, 'required' => [ 'videoType', '=', 'youtube' ], ]; $this->controls['youtubeDisableKeyboard'] = [ 'tab' => 'content', 'label' => esc_html__( 'Disable keyboard controls', 'bricks' ), 'type' => 'checkbox', 'required' => [ 'videoType', '=', 'youtube' ], ]; $this->controls['youtubeLanguage'] = [ 'tab' => 'content', 'label' => esc_html__( 'Interface language', 'bricks' ), 'type' => 'text', 'placeholder' => 'en', 'inline' => true, 'info' => esc_html__( 'ISO 639-1 two-letter language code (e.g., en, fr, de)', 'bricks' ), 'required' => [ 'videoType', '=', 'youtube' ], ]; $this->controls['youtubeCcLang'] = [ 'tab' => 'content', 'label' => esc_html__( 'Captions language', 'bricks' ), 'type' => 'text', 'placeholder' => 'en', 'inline' => true, 'info' => esc_html__( 'ISO 639-1 two-letter language code for default captions', 'bricks' ), 'required' => [ 'videoType', '=', 'youtube' ], ]; $this->controls['youtubeCcLoad'] = [ 'tab' => 'content', 'label' => esc_html__( 'Show captions by default', 'bricks' ), 'type' => 'checkbox', 'required' => [ 'videoType', '=', 'youtube' ], ]; $this->controls['youtubeColor'] = [ 'tab' => 'content', 'label' => esc_html__( 'Progress bar color', 'bricks' ), 'type' => 'select', 'options' => [ 'red' => esc_html__( 'Red', 'bricks' ), 'white' => esc_html__( 'White', 'bricks' ), ], 'placeholder' => esc_html__( 'Red', 'bricks' ), 'inline' => true, 'required' => [ 'videoType', '=', 'youtube' ], ]; $this->controls['youtubeHideAnnotationsByDefault'] = [ 'tab' => 'content', 'label' => esc_html__( 'Hide video annotations by default', 'bricks' ), 'type' => 'checkbox', 'default' => true, 'required' => [ 'videoType', '=', 'youtube' ], ]; $this->controls['youtubePlaysinline'] = [ 'tab' => 'content', 'label' => esc_html__( 'Play inline', 'bricks' ) . ' (iOS)', 'type' => 'checkbox', 'info' => esc_html__( 'Play videos inline instead of fullscreen on iOS devices.', 'bricks' ), 'required' => [ 'videoType', '=', 'youtube' ], ]; /** * Type: Vimeo */ $this->controls['vimeoId'] = [ 'tab' => 'content', 'label' => esc_html__( 'Vimeo video ID/URL', 'bricks' ), 'type' => 'text', 'inline' => false, 'required' => [ 'videoType', '=', 'vimeo' ], ]; // Support unlisted vimeo videos. $this->controls['vimeoHash'] = [ 'tab' => 'content', 'label' => esc_html__( 'Vimeo privacy hash', 'bricks' ), 'type' => 'text', 'inline' => true, 'info' => esc_html__( 'If the video is unlisted, you will need to enter the video privacy hash.', 'bricks' ), 'required' => [ 'videoType', '=', 'vimeo' ], ]; // Cannot be used if using preview image $this->controls['vimeoAutoplay'] = [ 'tab' => 'content', 'label' => esc_html__( 'Autoplay', 'bricks' ), 'type' => 'checkbox', 'required' => [ [ 'videoType', '=', 'vimeo' ], [ 'previewImage' , '!=', true ], ], ]; $this->controls['vimeoLoop'] = [ 'tab' => 'content', 'label' => esc_html__( 'Loop', 'bricks' ), 'type' => 'checkbox', 'required' => [ 'videoType', '=', 'vimeo' ], ]; $this->controls['vimeoMute'] = [ 'tab' => 'content', 'label' => esc_html__( 'Mute', 'bricks' ), 'type' => 'checkbox', 'required' => [ 'videoType', '=', 'vimeo' ], ]; $this->controls['vimeoByline'] = [ 'tab' => 'content', 'label' => esc_html__( 'Byline', 'bricks' ), 'type' => 'checkbox', 'default' => true, 'required' => [ 'videoType', '=', 'vimeo' ], ]; $this->controls['vimeoTitle'] = [ 'tab' => 'content', 'label' => esc_html__( 'Title', 'bricks' ), 'type' => 'checkbox', 'default' => true, 'required' => [ 'videoType', '=', 'vimeo' ], ]; $this->controls['vimeoPortrait'] = [ 'tab' => 'content', 'label' => esc_html__( 'User portrait', 'bricks' ), 'type' => 'checkbox', 'default' => true, 'required' => [ 'videoType', '=', 'vimeo' ], ]; $this->controls['vimeoDoNotTrack'] = [ 'tab' => 'content', 'label' => esc_html__( 'Do not track', 'bricks' ), 'type' => 'checkbox', 'required' => [ 'videoType', '=', 'vimeo' ], ]; $this->controls['vimeoColor'] = [ 'tab' => 'content', 'label' => esc_html__( 'Color', 'bricks' ), 'type' => 'color', 'required' => [ 'videoType', '=', 'vimeo' ], ]; /** * Preview image * * Load video YouTube/Vimeo iframe after preview image click. * * Cannot be used with autoplay. * * @since 1.7.2 */ $this->controls['previewImageSeparator'] = [ 'tab' => 'content', 'type' => 'separator', 'label' => esc_html__( 'Preview image', 'bricks' ), 'description' => esc_html__( 'The video <iframe> is lazy loaded after clicking the preview image.', 'bricks' ), 'required' => [ [ 'videoType', '=', [ 'vimeo', 'youtube' ] ], ], ]; $this->controls['previewImage'] = [ 'tab' => 'content', 'type' => 'select', 'options' => [ 'default' => esc_html__( 'Default', 'bricks' ) . ' (API)', 'custom' => esc_html__( 'Custom', 'bricks' ), ], 'placeholder' => esc_html__( 'None', 'bricks' ), 'description' => esc_html__( 'Fallback preview image', 'bricks' ) . ':<br> ' . esc_html__( 'Settings', 'bricks' ) . ' > ' . esc_html__( 'Theme Styles', 'bricks' ) . ' > ' . esc_html__( 'Element', 'bricks' ) . ' > ' . esc_html__( 'Video', 'bricks' ), 'required' => [ [ 'videoType', '=', [ 'vimeo', 'youtube' ] ], ], ]; $this->controls['previewImageCustom'] = [ 'tab' => 'content', 'type' => 'image', 'required' => [ [ 'videoType', '=', [ 'vimeo', 'youtube' ] ], [ 'previewImage', '=', 'custom' ], ], ]; $this->controls['previewImageSize'] = [ 'tab' => 'content', 'label' => esc_html__( 'Image size', 'bricks' ), 'type' => 'select', 'options' => [ 'default' => esc_html__( 'Default', 'bricks' ) . ' (120x90)', 'mqdefault' => esc_html__( 'Medium', 'bricks' ) . ' (320x180)', 'hqdefault' => esc_html__( 'High', 'bricks' ) . ' (480x360)', 'sddefault' => esc_html__( 'Standard', 'bricks' ) . ' (640x480)', 'maxresdefault' => esc_html__( 'Maximum', 'bricks' ) . ' (1280x720)', ], 'placeholder' => esc_html__( 'High', 'bricks' ) . ' (480x360)', 'required' => [ [ 'videoType', '=', 'youtube' ], [ 'previewImage', '=', 'default' ], ], ]; $this->controls['previewImageIconInfo'] = [ 'tab' => 'content', 'type' => 'info', 'content' => esc_html__( 'Set "Icon" as video play button for a better user experience.', 'bricks' ), 'required' => [ [ 'previewImage', '!=', '' ], [ 'overlayIcon', '=', '' ], ], ]; $this->controls['previewImageYoutubeAutoplayInfo'] = [ 'tab' => 'content', 'type' => 'info', 'content' => esc_html__( 'Autoplay is not supported when using preview image.', 'bricks' ), 'required' => [ [ 'previewImage', '!=', '' ], [ 'youtubeAutoplay', '!=', '' ], ], ]; $this->controls['previewImageVimeoAutoplay'] = [ 'tab' => 'content', 'type' => 'info', 'content' => esc_html__( 'Autoplay is not supported when using preview image.', 'bricks' ), 'required' => [ [ 'previewImage', '!=', '' ], [ 'vimeoAutoplay', '!=', '' ], ], ]; /** * Type: Media */ $this->controls['media'] = [ 'tab' => 'content', 'label' => esc_html__( 'Media', 'bricks' ), 'type' => 'video', 'required' => [ 'videoType', '=', 'media' ], ]; /** * Type: File */ $this->controls['fileUrl'] = [ 'tab' => 'content', 'label' => esc_html__( 'Video file URL', 'bricks' ), 'type' => 'text', 'required' => [ 'videoType', '=', 'file' ], ]; /** * Type: Meta */ $this->controls['useDynamicData'] = [ 'tab' => 'content', 'label' => '', 'type' => 'text', 'placeholder' => esc_html__( 'Select dynamic data', 'bricks' ), 'hasDynamicData' => 'link', 'required' => [ 'videoType', '=', 'meta' ], ]; /** * Type: Media & File */ $this->controls['filePreload'] = [ 'tab' => 'content', 'label' => esc_html__( 'Preload', 'bricks' ), 'type' => 'select', 'options' => [ 'metadata' => 'metadata', 'auto' => 'auto', 'none' => 'none', ], 'placeholder' => esc_html__( 'Default', 'bricks' ), 'inline' => true, 'required' => [ 'videoType', '=', [ 'media', 'file', 'meta' ] ], ]; $this->controls['fileAutoplay'] = [ 'tab' => 'content', 'label' => esc_html__( 'Autoplay', 'bricks' ), 'type' => 'checkbox', 'required' => [ 'videoType', '=', [ 'media', 'file', 'meta' ] ], ]; $this->controls['fileLoop'] = [ 'tab' => 'content', 'label' => esc_html__( 'Loop', 'bricks' ), 'type' => 'checkbox', 'required' => [ 'videoType', '=', [ 'media', 'file', 'meta' ] ], ]; $this->controls['fileMute'] = [ 'tab' => 'content', 'label' => esc_html__( 'Mute', 'bricks' ), 'type' => 'checkbox', 'required' => [ 'videoType', '=', [ 'media', 'file', 'meta' ] ], ]; $this->controls['fileInline'] = [ 'tab' => 'content', 'label' => esc_html__( 'Play inline', 'bricks' ), 'type' => 'checkbox', 'required' => [ 'videoType', '=', [ 'media', 'file', 'meta' ] ], ]; $this->controls['fileControls'] = [ 'tab' => 'content', 'label' => esc_html__( 'Controls', 'bricks' ), 'type' => 'checkbox', 'default' => true, 'required' => [ 'videoType', '=', [ 'media', 'file', 'meta' ] ], ]; $this->controls['fileControlNoDownload'] = [ 'tab' => 'content', 'label' => esc_html__( 'Disable', 'bricks' ) . ': ' . esc_html__( 'Download', 'bricks' ), 'info' => 'Firefox: ' . esc_html__( 'Not supported', 'bricks' ) . ' (controlslist)', 'type' => 'checkbox', 'required' => [ [ 'videoType', '=', [ 'media', 'file', 'meta' ] ], [ 'fileControls', '=', true ], ], ]; $this->controls['fileControlNoFullscreen'] = [ 'tab' => 'content', 'label' => esc_html__( 'Disable', 'bricks' ) . ': ' . esc_html__( 'Fullscreen', 'bricks' ), 'info' => 'Firefox: ' . esc_html__( 'Not supported', 'bricks' ) . ' (controlslist)', 'type' => 'checkbox', 'required' => [ [ 'videoType', '=', [ 'media', 'file', 'meta' ] ], [ 'fileControls', '=', true ], ], ]; $this->controls['fileControlNoRemotePlayback'] = [ 'tab' => 'content', 'label' => esc_html__( 'Disable', 'bricks' ) . ': ' . esc_html__( 'Remote playback', 'bricks' ), 'info' => 'Firefox: ' . esc_html__( 'Not supported', 'bricks' ) . ' (controlslist)', 'type' => 'checkbox', 'required' => [ [ 'videoType', '=', [ 'media', 'file', 'meta' ] ], [ 'fileControls', '=', true ], ], ]; $this->controls['infoControls'] = [ 'tab' => 'content', 'content' => esc_html__( 'Set individual video player controls under: Settings > Theme Styles > Element - Video', 'bricks' ), 'type' => 'info', 'required' => [ 'videoType', '=', [ 'media', 'file', 'meta' ] ], ]; $this->controls['videoPoster'] = [ 'tab' => 'content', 'label' => esc_html__( 'Poster', 'bricks' ), 'type' => 'image', 'description' => esc_html__( 'Set for video SEO best practices via poster attribute on the video tag. If the source is Youtube or Vimeo, it will be used as preview image.', 'bricks' ), 'required' => [ 'videoType', '=', [ 'media', 'file', 'meta' ] ], ]; // OVERLAY / ICON $this->controls['overlay'] = [ 'tab' => 'content', 'group' => 'icon', 'type' => 'background', 'label' => esc_html__( 'Overlay', 'bricks' ), 'exclude' => 'video', 'rerender' => true, 'css' => [ [ 'property' => 'background', 'selector' => '.bricks-video-overlay', ], ], ]; $this->controls['overlayIcon'] = [ 'tab' => 'content', 'group' => 'icon', 'label' => esc_html__( 'Icon', 'bricks' ), 'type' => 'icon', 'rerender' => true, ]; // aria-label for icon/overlay (@since 1.11) $this->controls['overlayAriaLabel'] = [ 'tab' => 'content', 'group' => 'icon', 'label' => 'aria-label', 'type' => 'text', 'inline' => true, 'hasDynamicData' => true, 'description' => esc_html__( 'Added to icon. If there is no icon, it will be added to the overlay.', 'bricks' ), ]; $this->controls['overlayIconTypography'] = [ 'tab' => 'content', 'group' => 'icon', 'label' => esc_html__( 'Icon typography', 'bricks' ), 'type' => 'typography', 'css' => [ [ 'property' => 'font', 'selector' => '.bricks-video-overlay-icon', ], ], 'exclude' => [ 'font-family', 'font-weight', 'font-style', 'text-align', 'text-decoration', 'text-transform', 'line-height', 'letter-spacing', ], 'required' => [ 'overlayIcon.icon', '!=', '' ], ]; $this->controls['overlayIconPadding'] = [ 'tab' => 'content', 'group' => 'icon', 'label' => esc_html__( 'Icon padding', 'bricks' ), 'type' => 'spacing', 'css' => [ [ 'property' => 'padding', 'selector' => '.bricks-video-overlay-icon', ], ], 'required' => [ 'overlayIcon', '!=', '' ], ]; $this->controls['overlayIconBackgroundColor'] = [ 'tab' => 'content', 'group' => 'icon', 'label' => esc_html__( 'Icon background color', 'bricks' ), 'type' => 'color', 'css' => [ [ 'property' => 'background-color', 'selector' => '.bricks-video-overlay-icon', ], ], 'required' => [ 'overlayIcon', '!=', '' ], ]; $this->controls['overlayIconBorder'] = [ 'tab' => 'content', 'group' => 'icon', 'label' => esc_html__( 'Icon border', 'bricks' ), 'type' => 'border', 'css' => [ [ 'property' => 'border', 'selector' => '.bricks-video-overlay-icon', ], ], 'required' => [ 'overlayIcon', '!=', '' ], ]; $this->controls['overlayIconBoxShadow'] = [ 'tab' => 'content', 'group' => 'icon', 'label' => esc_html__( 'Icon box shadow', 'bricks' ), 'type' => 'box-shadow', 'css' => [ [ 'property' => 'box-shadow', 'selector' => '.bricks-video-overlay-icon', ], ], 'required' => [ 'overlayIcon', '!=', '' ], ]; } public function render() { $settings = $this->settings; // Return: No video type selected if ( empty( $settings['videoType'] ) ) { return $this->render_element_placeholder( [ 'title' => esc_html__( 'No video selected.', 'bricks' ), ] ); } // Parse settings if videoType = 'meta' try fitting content into the other 'videoType' flows $settings = $this->get_normalized_video_settings( $settings ); $source = $settings['videoType'] ?? false; if ( $source === 'youtube' && empty( $settings['youTubeId'] ) ) { return $this->render_element_placeholder( [ 'title' => esc_html__( 'No YouTube ID provided.', 'bricks' ), ] ); } if ( $source === 'vimeo' && empty( $settings['vimeoId'] ) ) { return $this->render_element_placeholder( [ 'title' => esc_html__( 'No Vimeo ID provided.', 'bricks' ), ] ); } if ( $source === 'media' && empty( $settings['media'] ) ) { return $this->render_element_placeholder( [ 'title' => esc_html__( 'No video selected.', 'bricks' ), ] ); } if ( $source === 'file' && empty( $settings['fileUrl'] ) ) { return $this->render_element_placeholder( [ 'title' => esc_html__( 'No file URL provided.', 'bricks' ), ] ); } // If meta is still set, then something failed if ( $source === 'meta' ) { if ( empty( $settings['useDynamicData'] ) ) { $message = esc_html__( 'No dynamic data set.', 'bricks' ); } else { $message = esc_html__( 'Dynamic data is empty.', 'bricks' ); } if ( ! empty( $message ) ) { return $this->render_element_placeholder( [ 'title' => $message ] ); } } // Build video URL $video_url = ''; $video_parameters = []; // Use custom HTML5 video player: https://plyr.io (if controls are enabled) $use_custom_player = isset( $this->theme_styles['customPlayer'] ) && isset( $settings['fileControls'] ); switch ( $source ) { case 'youtube': $video_url = "https://www.youtube.com/embed/{$settings['youTubeId']}?"; if ( isset( $settings['youtubeDoNotTrack'] ) ) { $video_url = "https://www.youtube-nocookie.com/embed/{$settings['youTubeId']}?"; } // https://developers.google.com/youtube/player_parameters $video_parameters[] = 'wmode=opaque'; if ( isset( $settings['youtubeAutoplay'] ) ) { $video_parameters[] = 'autoplay=1'; } if ( ! isset( $settings['youtubeControls'] ) ) { $video_parameters[] = 'controls=0'; } if ( isset( $settings['youtubeLoop'] ) ) { // Loop in iframe requires 'playlist' parameter. $video_parameters[] = "loop=1&playlist={$settings['youTubeId']}"; } if ( isset( $settings['youtubeMute'] ) ) { $video_parameters[] = 'mute=1'; } if ( ! isset( $settings['youtubeRel'] ) ) { $video_parameters[] = 'rel=0'; } // Add enablejsapi to autopause on bricks/popup/close (@since 1.8) $video_parameters[] = 'enablejsapi=1'; // Add origin parameter for security when using enablejsapi (@since 2.2) // https://developers.google.com/youtube/player_parameters#origin if ( ! empty( $_SERVER['HTTP_HOST'] ) ) { $protocol = is_ssl() ? 'https://' : 'http://'; $video_parameters[] = 'origin=' . urlencode( $protocol . $_SERVER['HTTP_HOST'] ); } // New parameters (@since 2.2) if ( ! empty( $settings['youtubeStart'] ) ) { $video_parameters[] = 'start=' . absint( $settings['youtubeStart'] ); } if ( ! empty( $settings['youtubeEnd'] ) ) { $video_parameters[] = 'end=' . absint( $settings['youtubeEnd'] ); } if ( isset( $settings['youtubeDisableFullscreenButton'] ) ) { $video_parameters[] = 'fs=0'; } if ( isset( $settings['youtubeDisableKeyboard'] ) ) { $video_parameters[] = 'disablekb=1'; } if ( ! empty( $settings['youtubeLanguage'] ) ) { $video_parameters[] = 'hl=' . sanitize_text_field( $settings['youtubeLanguage'] ); } if ( ! empty( $settings['youtubeCcLang'] ) ) { $video_parameters[] = 'cc_lang_pref=' . sanitize_text_field( $settings['youtubeCcLang'] ); } if ( isset( $settings['youtubeCcLoad'] ) ) { $video_parameters[] = 'cc_load_policy=1'; } if ( ! empty( $settings['youtubeColor'] ) ) { $video_parameters[] = 'color=' . sanitize_text_field( $settings['youtubeColor'] ); } if ( ! isset( $settings['youtubeHideAnnotationsByDefault'] ) ) { $video_parameters[] = 'iv_load_policy=3'; } if ( isset( $settings['youtubePlaysinline'] ) ) { $video_parameters[] = 'playsinline=1'; } break; case 'vimeo': $video_url = "https://player.vimeo.com/video/{$settings['vimeoId']}?"; // https://developer.vimeo.com/apis/oembed#arguments if ( isset( $settings['vimeoAutoplay'] ) ) { $video_parameters[] = 'autoplay=1'; } if ( isset( $settings['vimeoHash'] ) ) { $video_parameters[] = 'h=' . $settings['vimeoHash']; } if ( isset( $settings['vimeoLoop'] ) ) { $video_parameters[] = 'loop=1'; } if ( isset( $settings['vimeoMute'] ) ) { $video_parameters[] = 'muted=1'; } if ( ! isset( $settings['vimeoByline'] ) ) { $video_parameters[] = 'byline=0'; } if ( ! isset( $settings['vimeoTitle'] ) ) { $video_parameters[] = 'title=0'; } if ( ! isset( $settings['vimeoPortrait'] ) ) { $video_parameters[] = 'portrait=0'; } if ( isset( $settings['vimeoDoNotTrack'] ) ) { $video_parameters[] = 'dnt=1'; } if ( ! empty( $settings['vimeoColor']['hex'] ) ) { $vimeo_color = str_replace( '#', '', $settings['vimeoColor']['hex'] ); $video_parameters[] = "color={$vimeo_color}"; } break; case 'media': case 'file': if ( $source === 'media' && ! empty( $settings['media']['url'] ) ) { $video_url = esc_url( $settings['media']['url'] ); } elseif ( $source === 'file' && ! empty( $settings['fileUrl'] ) ) { $video_url = esc_url( bricks_render_dynamic_data( $settings['fileUrl'] ) ); } $video_classes = []; if ( $this->lazy_load() ) { $video_classes = [ 'bricks-lazy-hidden' ]; $this->set_attribute( 'video', 'data-src', $video_url ); } else { $this->set_attribute( 'video', 'src', $video_url ); } // Load custom video player if enabled if ( $use_custom_player ) { $video_classes[] = 'bricks-plyr'; } $this->set_attribute( 'video', 'class', $video_classes ); if ( isset( $settings['filePreload'] ) ) { $this->set_attribute( 'video', 'preload', $settings['filePreload'] ); } if ( isset( $settings['fileAutoplay'] ) ) { $this->set_attribute( 'video', 'autoplay' ); // Necessary for autoplaying in iOS (https://webkit.org/blog/6784/new-video-policies-for-ios/) $this->set_attribute( 'video', 'playsinline' ); } elseif ( isset( $settings['fileInline'] ) ) { $this->set_attribute( 'video', 'playsinline' ); } if ( isset( $settings['fileControls'] ) ) { $this->set_attribute( 'video', 'controls' ); // No download if ( isset( $settings['fileControlNoDownload'] ) ) { $this->set_attribute( 'video', 'controlslist', 'nodownload' ); } // No fullscreen if ( isset( $settings['fileControlNoFullscreen'] ) ) { $this->set_attribute( 'video', 'controlslist', 'nofullscreen' ); } // No remote playback if ( isset( $settings['fileControlNoRemotePlayback'] ) ) { $this->set_attribute( 'video', 'controlslist', 'noremoteplayback' ); } } elseif ( ! $use_custom_player ) { $this->set_attribute( 'video', 'onclick', 'this.paused ? this.play() : this.pause()' ); } if ( isset( $settings['fileLoop'] ) ) { $this->set_attribute( 'video', 'loop' ); } if ( isset( $settings['fileMute'] ) ) { $this->set_attribute( 'video', 'muted' ); } // Video poster (@since 1.8.5) $video_poster_image = $this->get_video_image_by_key( 'videoPoster' ); if ( ! empty( $video_poster_image['url'] ) ) { $this->set_attribute( 'video', 'poster', $video_poster_image['url'] ); } break; } // Set data-id so we could track the plyr instances $this->set_attribute( 'wrapper', 'data-id', Helpers::generate_random_id( false ) ); // Add parameters to final video URL if ( ! empty( $video_parameters ) ) { $video_url .= join( '&', $video_parameters ); } // STEP: Render // Video HTML wrapper with iframe / video element for popup and non-popup settings $output = "<div {$this->render_attributes( '_root' )}>"; $overlay_icon = ! empty( $settings['overlayIcon'] ) ? $settings['overlayIcon'] : false; // Check: Theme style for video 'overlayIcon' setting (@since 1.7) if ( ! $overlay_icon && ! empty( $this->theme_styles['overlayIcon'] ) ) { $overlay_icon = $this->theme_styles['overlayIcon']; } // Icon attributes $icon_attributes = [ 'class' => [ 'bricks-video-overlay-icon' ], 'tabindex' => '0', // Make icon focusable for keyboard navigation (@since 1.11) 'role' => 'button', ]; if ( ! empty( $settings['overlayAriaLabel'] ) ) { $icon_attributes['aria-label'] = wp_strip_all_tags( $this->render_dynamic_data( $settings['overlayAriaLabel'] ) ); } $icon = $overlay_icon ? self::render_icon( $overlay_icon, $icon_attributes ) : false; /** * Check: Element & theme style for 'overlay' setting @since 1.7 * Use new helper function to check for 'overlay' setting from different breakpoints (@since 1.8) * Moved this check here, since we use $has_overlay in multiple places (@since 1.11) */ $has_overlay = Helpers::element_setting_has_value( 'overlay', $settings ) || Helpers::element_setting_has_value( 'overlay', $this->theme_styles ); if ( $use_custom_player ) { $video_config_plyr = []; // https://github.com/sampotts/plyr/blob/master/controls.md if ( isset( $settings['fileControls'] ) ) { $video_config_plyr['controls'] = [ 'play' ]; // Play button (if no custom icon is set) if ( ! $icon ) { $video_config_plyr['controls'][] = 'play-large'; } if ( isset( $this->theme_styles['fileRestart'] ) ) { $video_config_plyr['controls'][] = 'restart'; } if ( isset( $this->theme_styles['fileRewind'] ) ) { $video_config_plyr['controls'][] = 'rewind'; } if ( isset( $this->theme_styles['fileFastForward'] ) ) { $video_config_plyr['controls'][] = 'fast-forward'; } $video_config_plyr['controls'][] = 'current-time'; $video_config_plyr['controls'][] = 'duration'; $video_config_plyr['controls'][] = 'progress'; $video_config_plyr['controls'][] = 'mute'; $video_config_plyr['controls'][] = 'volume'; if ( isset( $this->theme_styles['fileSpeed'] ) ) { $video_config_plyr['controls'][] = 'settings'; } if ( isset( $this->theme_styles['filePip'] ) ) { $video_config_plyr['controls'][] = 'pip'; } if ( ! isset( $settings['fileControlNoFullscreen'] ) ) { $video_config_plyr['controls'][] = 'fullscreen'; } } if ( isset( $settings['fileMute'] ) ) { $video_config_plyr['muted'] = true; // Store false required for muted to take effect $video_config_plyr['storage'] = false; } $this->set_attribute( 'video', 'data-plyr-config', wp_json_encode( $video_config_plyr ) ); } if ( $source === 'media' || $source === 'file' || $source === 'meta' ) { // If there is an overlay, add tabindex="-1" to video element (@since 1.11) // to prevent tabbing to it, when overlay is enabled if ( $has_overlay ) { $this->set_attribute( 'video', 'tabindex', '-1' ); } $output .= '<video ' . $this->render_attributes( 'video' ) . '>'; $output .= '<p>' . esc_html__( 'Your browser does not support the video tag.', 'bricks' ) . '</p>'; $output .= '</video>'; } if ( $source === 'youtube' || $source === 'vimeo' ) { // Set proper iframe attributes for YouTube/Vimeo (@since 2.2) $this->set_attribute( 'iframe', 'loading', 'lazy' ); // YouTube-specific attributes to fix error 153 and enable API features (@since 2.2) if ( $source === 'youtube' ) { $this->set_attribute( 'iframe', 'allow', 'accelerometer; autoplay; clipboard-write; encrypted-media; fullscreen; gyroscope; picture-in-picture; web-share' ); $this->set_attribute( 'iframe', 'referrerpolicy', 'strict-origin-when-cross-origin' ); } // Vimeo-specific attributes to enable API features (@since 2.3) if ( $source === 'vimeo' ) { $this->set_attribute( 'iframe', 'allow', 'autoplay; fullscreen; picture-in-picture' ); // Add specific attributes (https://help.vimeo.com/hc/en-us/articles/12425790245777-Troubleshoot-Fullscreen-button-missing-from-the-player) $this->set_attribute( 'iframe', 'mozallowfullscreen' ); $this->set_attribute( 'iframe', 'webkitallowfullscreen' ); $this->set_attribute( 'iframe', 'allowfullscreen' ); } // If there is an overlay, add tabindex="-1" to iframe element (@since 1.11) // to prevent tabbing to it, when overlay is enabled if ( $has_overlay ) { $this->set_attribute( 'iframe', 'tabindex', '-1' ); } if ( ! empty( $settings['iframeTitle'] ) ) { $this->set_attribute( 'iframe', 'title', wp_strip_all_tags( $this->render_dynamic_data( $settings['iframeTitle'] ) ) ); } // STEP: Render YouTube/Vimeo iframe or div with background image $preview_image_url = $this->get_preview_image_url( $settings ); // STEP: Maybe user use Dynamic Data + Video Poster field for YouTube/Vimeo (@since 1.12.2) if ( empty( $preview_image_url ) && isset( $settings['videoPoster'] ) ) { // Try to get video poster image $video_poster_image = $this->get_video_image_by_key( 'videoPoster' ); // If there is a video poster image, use it as preview image if ( ! empty( $video_poster_image['url'] ) ) { $preview_image_url = $video_poster_image['url']; } } if ( $preview_image_url ) { // STEP: Render div with background image when video lazy load is enabled and autoplay is disabled $this->set_attribute( 'iframe', 'data-iframe-src', $video_url ); $this->set_attribute( 'iframe', 'class', 'bricks-video-preview-image' ); // If there is no overlay and no icon, set tabindex to 0, so that it can be focused (@since 1.11) if ( ! $has_overlay && ! $icon ) { $this->set_attribute( 'iframe', 'tabindex', '0' ); } $background_style = "background-image: url($preview_image_url);"; // STEP: Add background image to div if ( $background_style ) { if ( $this->lazy_load() ) { // STEP: Global lazy load is enabled, background image added as data-style attribute $this->set_attribute( 'iframe', 'data-style', $background_style ); $this->set_attribute( 'iframe', 'class', 'bricks-lazy-hidden' ); } else { // STEP: Global lazy load is enabled, background image added as data-style attribute $this->set_attribute( 'iframe', 'style', $background_style ); } } // Render as div $output .= '<div ' . $this->render_attributes( 'iframe' ) . '></div>'; } // STEP: Render iframe (when video lazy load is disabled or autoplay is enabled) else { if ( $this->lazy_load() ) { // STEP: Global lazy load is enabled, iframe src added as data-src attribute $this->set_attribute( 'iframe', 'data-src', $video_url ); $this->set_attribute( 'iframe', 'class', 'bricks-lazy-hidden' ); } else { $this->set_attribute( 'iframe', 'src', $video_url ); } // Render as iframe $output .= '<iframe ' . $this->render_attributes( 'iframe' ) . '></iframe>'; } } // Check: Element classes for 'overlay' setting (@since 1.7.1) $element_class_has_overlay = $this->element_classes_have( 'overlay' ); if ( $element_class_has_overlay ) { $has_overlay = true; } if ( $has_overlay ) { if ( empty( $icon ) ) { // If no icon is set, set tabindex to 0, to overlay element, so that it can be focused (@since 1.11) $this->set_attribute( 'video-overlay', 'tabindex', '0' ); $this->set_attribute( 'video-overlay', 'role', 'button' ); // @since 1.11: Add aria-label to overlay, if there is no icon, but there is overlay if ( ! empty( $settings['overlayAriaLabel'] ) ) { $this->set_attribute( 'video-overlay', 'aria-label', wp_strip_all_tags( $this->render_dynamic_data( $settings['overlayAriaLabel'] ) ) ); } } if ( $this->lazy_load() ) { $output .= '<div class="bricks-lazy-hidden bricks-video-overlay" ' . $this->render_attributes( 'video-overlay' ) . '></div>'; } else { $output .= '<div class="bricks-video-overlay" ' . $this->render_attributes( 'video-overlay' ) . '></div>'; } } if ( $icon ) { $output .= $icon; } $output .= '</div>'; echo $output; } public function convert_element_settings_to_block( $settings ) { $settings = $this->get_normalized_video_settings( $settings ); $source = ! empty( $settings['videoType'] ) ? $settings['videoType'] : false; $attrs = []; $output = ''; // Video Type: Media file / File URL if ( $source === 'media' || $source === 'file' ) { $block['blockName'] = 'core/video'; if ( isset( $settings['media']['id'] ) ) { $attrs['id'] = $settings['media']['id']; } $output = '<figure class="wp-block-video"><video '; if ( isset( $settings['fileAutoplay'] ) ) { $output .= 'autoplay '; } if ( isset( $settings['fileControls'] ) ) { $output .= 'controls '; } if ( isset( $settings['fileLoop'] ) ) { $output .= 'loop '; } if ( isset( $settings['fileMute'] ) ) { $output .= 'muted '; } if ( isset( $settings['filePreload'] ) ) { $output .= 'preload="' . $settings['filePreload'] . '"'; } if ( $source === 'media' ) { $output .= 'src="' . wp_get_attachment_url( intval( $settings['media']['id'] ) ) . '"'; } if ( $source === 'file' ) { $output .= 'src="' . esc_url( $settings['fileUrl'] ) . '"'; } if ( isset( $settings['fileInline'] ) ) { $output .= ' playsinline'; } $output .= '></video></figure>'; } // Video Type: YouTube if ( $source === 'youtube' && isset( $settings['youTubeId'] ) ) { $block = [ 'blockName' => 'core-embed/youtube' ]; $attrs['url'] = "https://www.youtube.com/watch?v={$settings['youTubeId']}"; if ( isset( $settings['youtubeDoNotTrack'] ) ) { $attrs['url'] = "https://www.youtube-nocookie.com/watch?v={$settings['youTubeId']}"; } $attrs['providerNameSlug'] = 'youtube'; $attrs['type'] = 'video'; $output = '<figure class="wp-block-embed-youtube wp-block-embed is-type-video is-provider-youtube"><div class="wp-block-embed__wrapper">' . $attrs['url'] . '</div></figure>'; } // Video Type: Vimeo if ( $source === 'vimeo' && isset( $settings['vimeoId'] ) ) { $block = [ 'blockName' => 'core-embed/vimeo' ]; $attrs['url'] = 'https://www.vimeo.com/' . $settings['vimeoId']; $attrs['providerNameSlug'] = 'vimeo'; $attrs['type'] = 'video'; $output = '<figure class="wp-block-embed-vimeo wp-block-embed is-type-video is-provider-vimeo"><div class="wp-block-embed__wrapper">' . $attrs['url'] . '</div></figure>'; } $block['attrs'] = $attrs; $block['innerContent'] = [ $output ]; return $block; } public function convert_block_to_element_settings( $block, $attributes ) { $video_provider = isset( $attributes['providerNameSlug'] ) ? $attributes['providerNameSlug'] : false; // Type: YouTube if ( $video_provider === 'youtube' ) { // Get YouTube video ID parse_str( parse_url( $attributes['url'], PHP_URL_QUERY ), $url_params ); return [ 'videoType' => 'youtube', 'youTubeId' => $url_params['v'], 'youtubeControls' => true, ]; } // Type: Vimeo if ( $video_provider === 'vimeo' ) { // Get Vimeo video ID $url_parts = explode( '/', $attributes['url'] ); $video_url = ''; foreach ( $url_parts as $url_part ) { if ( is_numeric( $url_part ) ) { $video_url = $url_part; } } return [ 'videoType' => 'vimeo', 'vimeoId' => $video_url, 'vimeoControls' => true, ]; } $output = $block['innerHTML']; // Type: Media file $media_video_id = isset( $attributes['id'] ) ? intval( $attributes['id'] ) : 0; if ( $media_video_id ) { $media = [ 'id' => $media_video_id, 'filename' => basename( get_attached_file( $media_video_id ) ), 'url' => wp_get_attachment_url( $media_video_id ), // 'mime' => '', ]; $element_settings = [ 'videoType' => 'media', 'media' => $media, 'fileAutoplay' => strpos( $output, ' autoplay' ) !== false, 'fileControls' => strpos( $output, ' controls' ) !== false, 'fileLoop' => strpos( $output, ' loop' ) !== false, 'fileMute' => strpos( $output, ' muted' ) !== false, 'fileInline' => strpos( $output, ' playsinline' ) !== false, ]; if ( strpos( $output, ' preload="auto"' ) !== false ) { $element_settings['filePreload'] = 'auto'; } return $element_settings; } // Type: File URL $video_url_parts = explode( '"', $output ); $video_url = ''; foreach ( $video_url_parts as $video_url_part ) { if ( filter_var( $video_url_part, FILTER_VALIDATE_URL ) ) { $video_url = $video_url_part; } } if ( $video_url ) { $element_settings = [ 'videoType' => 'file', 'fileUrl' => $video_url, 'fileAutoplay' => strpos( $output, ' autoplay' ) !== false, 'fileControls' => strpos( $output, ' controls' ) !== false, 'fileLoop' => strpos( $output, ' loop' ) !== false, 'fileMute' => strpos( $output, ' muted' ) !== false, 'fileInline' => strpos( $output, ' playsinline' ) !== false, ]; if ( strpos( $output, ' preload="auto"' ) !== false ) { $element_settings['filePreload'] = 'auto'; } return $element_settings; } } /** * Helper function to parse the settings when videoType = meta * * @return array */ public function get_normalized_video_settings( $settings = [] ) { if ( empty( $settings['videoType'] ) ) { return $settings; } if ( $settings['videoType'] === 'youtube' ) { if ( ! empty( $settings['youTubeId'] ) ) { $settings['youTubeId'] = $this->render_dynamic_data( $settings['youTubeId'] ); // Get YouTube video ID, if it's a full URL (@since 1.12.2) $settings['youTubeId'] = $this->get_youtube_id_from_url( $settings['youTubeId'] ); } if ( ! empty( $settings['iframeTitle'] ) ) { $settings['iframeTitle'] = $this->render_dynamic_data( $settings['iframeTitle'] ); } if ( ! empty( $settings['youtubeStart'] ) ) { $settings['youtubeStart'] = $this->render_dynamic_data( $settings['youtubeStart'] ); } if ( ! empty( $settings['youtubeEnd'] ) ) { $settings['youtubeEnd'] = $this->render_dynamic_data( $settings['youtubeEnd'] ); } return $settings; } if ( $settings['videoType'] === 'vimeo' ) { if ( ! empty( $settings['vimeoId'] ) ) { $settings['vimeoId'] = $this->render_dynamic_data( $settings['vimeoId'] ); // Get Vimeo ID, if it's a full URL (@since 1.12.2) $settings['vimeoId'] = $this->get_vimeo_id_from_url( $settings['vimeoId'] ); } if ( ! empty( $settings['iframeTitle'] ) ) { $settings['iframeTitle'] = $this->render_dynamic_data( $settings['iframeTitle'] ); } if ( ! empty( $settings['vimeoHash'] ) ) { $settings['vimeoHash'] = $this->render_dynamic_data( $settings['vimeoHash'] ); } return $settings; } // Check 'file' and 'meta' videoType for dynamic data $dynamic_data = false; if ( $settings['videoType'] === 'file' && ! empty( $settings['fileUrl'] ) && strpos( $settings['fileUrl'], '{' ) === 0 ) { $dynamic_data = $settings['fileUrl']; } if ( $settings['videoType'] === 'meta' && ! empty( $settings['useDynamicData'] ) ) { $dynamic_data = $settings['useDynamicData']; } if ( ! $dynamic_data ) { return $settings; } $meta_video_url = ''; // Set context to 'media' (@since 2.0) $meta_media_value = $this->render_dynamic_data_tag( $dynamic_data, 'media' ); /** * Ensure we have a non-empty array and the first element is an array * * Check includes/integrations/dynamic-data/providers/base.php * * @since 2.0 */ if ( is_array( $meta_media_value ) && ! empty( $meta_media_value[0] ) && is_array( $meta_media_value[0] ) ) { $url_or_id = $meta_media_value[0]['url'] ?? ''; if ( ! empty( $url_or_id ) ) { if ( is_numeric( $url_or_id ) ) { // Cast to int safely and get the attachment URL $attachment_url = wp_get_attachment_url( (int) $url_or_id ); if ( $attachment_url ) { // Force URL as string as we will be using preg_match, unknown plugin might change the type via wp_get_attachment_url $meta_video_url = (string) $attachment_url; } } else { // Force URL as string as we will be using preg_match $meta_video_url = (string) $url_or_id; } } } elseif ( is_string( $meta_media_value ) && ! empty( $meta_media_value ) ) { // If the value is a string, use it directly (the full URL can be provided via @fallback) $meta_video_url = $meta_media_value; } if ( empty( $meta_video_url ) ) { return $settings; } /** * Is YouTube video * * Regex from @see: https://gist.github.com/ghalusa/6c7f3a00fd2383e5ef33 * * @since 2.1: Support for YouTube Shorts and Live URLs */ if ( preg_match( '%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|shorts/|live/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', $meta_video_url, $matches ) ) { $settings['youTubeId'] = $matches[1]; $settings['videoType'] = 'youtube'; if ( isset( $settings['fileAutoplay'] ) ) { $settings['youtubeAutoplay'] = $settings['fileAutoplay']; } else { unset( $settings['youtubeAutoplay'] ); } if ( isset( $settings['fileControls'] ) ) { $settings['youtubeControls'] = $settings['fileControls']; } else { unset( $settings['youtubeControls'] ); } if ( isset( $settings['fileLoop'] ) ) { $settings['youtubeLoop'] = $settings['fileLoop']; } else { unset( $settings['youtubeLoop'] ); } if ( isset( $settings['fileMute'] ) ) { $settings['youtubeMute'] = $settings['fileMute']; } else { unset( $settings['youtubeMute'] ); } } // Is Vimeo video elseif ( preg_match( '%^https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)(?:[?]?.*)$%im', $meta_video_url, $matches ) ) { // Regex from @see: https://gist.github.com/anjan011/1fcecdc236594e6d700f $settings['vimeoId'] = $matches[3]; $settings['videoType'] = 'vimeo'; if ( isset( $settings['fileAutoplay'] ) ) { $settings['vimeoAutoplay'] = $settings['fileAutoplay']; } else { unset( $settings['vimeoAutoplay'] ); } if ( isset( $settings['fileLoop'] ) ) { $settings['vimeoLoop'] = $settings['fileLoop']; } else { unset( $settings['vimeoLoop'] ); } if ( isset( $settings['fileMute'] ) ) { $settings['vimeoMute'] = $settings['fileMute']; } else { unset( $settings['vimeoMute'] ); } } else { // Url of a video file (either hosted or external) $settings['fileUrl'] = $meta_video_url; $settings['videoType'] = 'file'; } // Later the settings are used to control the video and the custom field should not be present unset( $settings['useDynamicData'] ); return $settings; } /** * Get the video image image URL * * @param array $settings * * @since 1.7.2 */ public function get_preview_image_url( $settings = [] ) { // Get source from settings as parse settings already processed the dynamic data $source = $this->settings['videoType'] ?? false; // Return: Video type is not YouTube or Vimeo if ( ! in_array( $source, [ 'youtube', 'vimeo' ] ) ) { return false; } // Return: Autoplay enabled if ( ( $source === 'youtube' && isset( $settings['youtubeAutoplay'] ) || ( $source === 'vimeo' && isset( $settings['vimeoAutoplay'] ) ) ) ) { return false; } // Return: No perview image type set $preview_image_type = $this->settings['previewImage'] ?? ''; if ( ! $preview_image_type ) { return false; } $preview_image = $preview_image_type === 'custom' && ! empty( $this->settings['previewImageCustom'] ) ? $this->get_video_image_by_key( 'previewImageCustom' ) : false; // STEP: Preview image if ( ! empty( $preview_image['url'] ) ) { return $preview_image['url']; } // Default: Youtube or Vimeo image $video_type = $settings['videoType'] ?? false; // STEP: Get YouTube video preview image from API if ( $video_type === 'youtube' ) { $preview_size = $settings['previewImageSize'] ?? 'hqdefault'; return "https://img.youtube.com/vi/{$settings['youTubeId']}/{$preview_size}.jpg"; } // STEP: Get the Vimeo video preview image from API if ( $video_type === 'vimeo' ) { $video_data = wp_remote_get( "https://vimeo.com/api/v2/video/{$settings['vimeoId']}.json" ); // 404 error is returned if the video is not found, so we need to check for that if ( ! is_wp_error( $video_data ) && $video_data['response']['code'] !== 404 ) { $video_data = json_decode( $video_data['body'] ); // Ensure that the thumbnail_large exists before using it if ( ! empty( $video_data[0]->thumbnail_large ) ) { return $video_data[0]->thumbnail_large; } } } // Image source empty: Use Theme Style "Preview image fallback image" if ( ! empty( $this->theme_styles['previewImageFallback']['url'] ) ) { return $this->theme_styles['previewImageFallback']['url']; } } /** * Get the image by control key * * Similar to get_normalized_image_settings() in the image element. * * Might be a fix image, a dynamic data tag or external URL. * * @since 1.8.5 * * @return array */ public function get_video_image_by_key( $control_key = '' ) { if ( empty( $control_key ) ) { return []; } $image = isset( $this->settings[ $control_key ] ) ? $this->settings[ $control_key ] : false; if ( ! $image ) { return []; } // STEP: Set image size $image['size'] = isset( $image['size'] ) && ! empty( $image['size'] ) ? $image['size'] : BRICKS_DEFAULT_IMAGE_SIZE; // STEP: Image ID or URL from dynamic data if ( ! empty( $image['useDynamicData'] ) ) { $dynamic_image = $this->render_dynamic_data_tag( $image['useDynamicData'], 'image', [ 'size' => $image['size'] ] ); if ( ! empty( $dynamic_image[0] ) ) { if ( is_numeric( $dynamic_image[0] ) ) { // Use the image ID to populate and set $dynamic_image['url'] $image['id'] = $dynamic_image[0]; $image['url'] = wp_get_attachment_image_url( $image['id'], $image['size'] ); } else { $image['url'] = $dynamic_image[0]; } } else { return []; } } // Set image ID $image['id'] = empty( $image['id'] ) ? 0 : $image['id']; // Set image URL if ( ! isset( $image['url'] ) ) { $image['url'] = ! empty( $image['id'] ) ? wp_get_attachment_image_url( $image['id'], $image['size'] ) : false; } else { // Parse dynamic data in the external URL if ( ! empty( $image['external'] ) && strpos( $image['external'], '{' ) !== false && strpos( $image['external'], '}' ) !== false ) { // Use external url if contains a dynamic data tag (@since 1.11.1) $image['url'] = $this->render_dynamic_data( $image['external'] ); } else { $image['url'] = $this->render_dynamic_data( $image['url'] ); } } return $image; } /** * Get the YouTube video ID from a URL * * @param string $url * @return string $video_id * * @since 1.12.2 */ public function get_youtube_id_from_url( $url = '' ) { // If it's valid URL, extract the video ID if ( filter_var( $url, FILTER_VALIDATE_URL ) && preg_match( '%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|shorts/|live/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i', $url, $matches ) ) { // Regex from @see: https://gist.github.com/ghalusa/6c7f3a00fd2383e5ef33 // @since 2.0: Support for YouTube Shorts and Live URLs return $matches[1]; } return $url; } /** * Get the Vimeo video ID from a URL * * @param string $url * @return string $video_id * * @since 1.12.2 */ public function get_vimeo_id_from_url( $url = '' ) { // If it's valid URL, extract the video ID if ( filter_var( $url, FILTER_VALIDATE_URL ) && preg_match( '%^https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)(?:[?]?.*)$%im', $url, $matches ) ) { // Regex from @see: https://gist.github.com/anjan011/1fcecdc236594e6d700f return $matches[3]; } return $url; } }
修改文件时间
将文件时间修改为当前时间的前一年
删除文件