| |
| <?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| if (!defined('ABSPATH')) exit;
|
|
|
| class WCV_Capa_Video_Flatsome {
|
| const META_KEY_ID = '_wcv_video_attachment_id';
|
|
|
| public function __construct() {
|
|
|
| add_action('add_meta_boxes', [$this, 'add_metabox']);
|
| add_action('save_post_product', [$this, 'save_meta'], 10, 2);
|
|
|
|
|
| add_action('admin_enqueue_scripts', [$this, 'admin_assets']);
|
| add_action('admin_footer-post.php', [$this, 'admin_inline_js']);
|
| add_action('admin_footer-post-new.php', [$this, 'admin_inline_js']);
|
|
|
|
|
| add_filter('woocommerce_single_product_image_html', [$this, 'replace_main_image_html'], 9999, 2);
|
| add_filter('woocommerce_single_product_image_thumbnail_html', [$this, 'maybe_replace_featured_in_gallery'], 9999, 2);
|
|
|
|
|
| add_filter('woocommerce_get_product_thumbnail', [$this, 'replace_loop_thumbnail'], 9999, 4);
|
|
|
|
|
| add_action('wp_enqueue_scripts', [$this, 'frontend_styles']);
|
| add_action('wp_enqueue_scripts', [$this, 'frontend_scripts']);
|
| }
|
|
|
|
|
|
|
| public function add_metabox() {
|
| add_meta_box(
|
| 'wcv_capa_video',
|
| __('Vídeo de capa do produto', 'wc-video-capa-flatsome'),
|
| [$this, 'metabox_html'],
|
| 'product',
|
| 'side',
|
| 'default'
|
| );
|
| }
|
|
|
| public function metabox_html($post) {
|
| wp_nonce_field('wcv_save_video_meta', 'wcv_video_nonce');
|
| $attachment_id = (int) get_post_meta($post->ID, self::META_KEY_ID, true);
|
| $url = $attachment_id ? wp_get_attachment_url($attachment_id) : '';
|
| $mime = $attachment_id ? get_post_mime_type($attachment_id) : '';
|
| $filename = $url ? wp_basename($url) : '';
|
|
|
| echo '<p>' . esc_html__('Selecione um arquivo MP4, WebM ou GIF da biblioteca de mídia. O arquivo ficará hospedado no próprio site.', 'wc-video-capa-flatsome') . '</p>';
|
|
|
| echo '<div id="wcv-video-wrapper">';
|
| echo '<input type="hidden" id="wcv_video_attachment_id" name="wcv_video_attachment_id" value="' . esc_attr($attachment_id) . '">';
|
| echo '<input type="text" id="wcv_video_url" class="widefat" value="' . esc_attr($url) . '" placeholder="' . esc_attr__('Nenhum arquivo selecionado', 'wc-video-capa-flatsome') . '" readonly>';
|
| echo '<p style="margin-top:8px;">';
|
| echo '<button type="button" class="button" id="wcv_select_video">' . esc_html__('Selecionar/Enviar arquivo', 'wc-video-capa-flatsome') . '</button> ';
|
| echo '<button type="button" class="button" id="wcv_remove_video">' . esc_html__('Remover', 'wc-video-capa-flatsome') . '</button>';
|
| echo '</p>';
|
|
|
| if ($url) {
|
| echo '<div id="wcv_preview" style="margin-top:8px;">';
|
| if ($mime === 'image/gif') {
|
| echo '<img src="' . esc_url($url) . '" style="max-width:100%;height:auto;" alt="">';
|
| } else {
|
| echo '<video src="' . esc_url($url) . '" style="max-width:100%;height:auto;" controls preload="metadata"></video>';
|
| }
|
| echo '<p style="font-size:12px;color:#666;margin-top:6px;">' . esc_html($filename) . '</p>';
|
| echo '</div>';
|
| } else {
|
| echo '<div id="wcv_preview" style="display:none;margin-top:8px;"></div>';
|
| }
|
|
|
| echo '</div>';
|
| echo '<p style="font-size:12px;color:#666;">' . esc_html__('Dica: mantenha o arquivo otimizado (tamanho/bitrate) para melhor performance.', 'wc-video-capa-flatsome') . '</p>';
|
| }
|
|
|
| public function admin_assets($hook) {
|
| global $post;
|
| if (!in_array($hook, ['post-new.php', 'post.php'], true)) return;
|
| if (empty($post) || get_post_type($post) !== 'product') return;
|
| wp_enqueue_media();
|
| }
|
|
|
| public function admin_inline_js() {
|
| global $post;
|
| if (empty($post) || get_post_type($post) !== 'product') return;
|
| ?>
|
| <script>
|
| (function($){
|
| function isAllowed(mime){
|
| return ['video/mp4','video/webm','image/gif'].indexOf(mime) !== -1;
|
| }
|
| $(document).on('click', '#wcv_select_video', function(e){
|
| e.preventDefault();
|
| var frame = wp.media({
|
| title: 'Selecione um vídeo (MP4/WebM) ou GIF',
|
| library: { type: ['video','image'] },
|
| button: { text: 'Usar este arquivo' },
|
| multiple: false
|
| });
|
| frame.on('select', function(){
|
| var att = frame.state().get('selection').first().toJSON();
|
| if(!isAllowed(att.mime)){
|
| alert('Tipo de arquivo não permitido. Use MP4, WebM ou GIF.');
|
| return;
|
| }
|
| $('#wcv_video_url').val(att.url);
|
| $('#wcv_video_attachment_id').val(att.id);
|
|
|
| var preview = $('#wcv_preview').empty().show();
|
| if(att.mime === 'image/gif'){
|
| $('<img/>',{src:att.url,css:{maxWidth:'100%',height:'auto'}}).appendTo(preview);
|
| }else{
|
| $('<video/>',{src:att.url,controls:true,preload:'metadata',css:{maxWidth:'100%',height:'auto'}}).appendTo(preview);
|
| }
|
| });
|
| frame.open();
|
| });
|
|
|
| $(document).on('click', '#wcv_remove_video', function(e){
|
| e.preventDefault();
|
| $('#wcv_video_url').val('');
|
| $('#wcv_video_attachment_id').val('');
|
| $('#wcv_preview').hide().empty();
|
| });
|
| })(jQuery);
|
| </script>
|
| <?php
|
| }
|
|
|
| public function save_meta($post_id, $post) {
|
| if (!isset($_POST['wcv_video_nonce']) || !wp_verify_nonce($_POST['wcv_video_nonce'], 'wcv_save_video_meta')) return;
|
| if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
|
| if (!current_user_can('edit_product', $post_id)) return;
|
|
|
| $att_id = isset($_POST['wcv_video_attachment_id']) ? (int) $_POST['wcv_video_attachment_id'] : 0;
|
|
|
| if ($att_id) {
|
| $mime = get_post_mime_type($att_id);
|
| if (!in_array($mime, ['video/mp4','video/webm','image/gif'], true)) {
|
| return;
|
| }
|
| update_post_meta($post_id, self::META_KEY_ID, $att_id);
|
| } else {
|
| delete_post_meta($post_id, self::META_KEY_ID);
|
| }
|
| }
|
|
|
|
|
|
|
| public function frontend_styles() {
|
| $css = '
|
| .wcv-video-wrapper video.wcv-video{width:100%;height:auto;display:block;}
|
| .wcv-video-wrapper img{max-width:100%;height:auto;display:block;}
|
| .wcv-video-wrapper{position:relative;}
|
|
|
| /* Catálogo/listagem */
|
| .wcv-video-thumb-wrapper{display:block;position:relative;overflow:hidden;}
|
| .wcv-video-thumb-wrapper video.wcv-loop-video{
|
| width:100%;height:100%;display:block;object-fit:cover;background:#000;
|
| }
|
| ';
|
| wp_register_style('wcv-capa-video', false);
|
| wp_enqueue_style('wcv-capa-video');
|
| wp_add_inline_style('wcv-capa-video', $css);
|
| }
|
|
|
| public function frontend_scripts() {
|
|
|
| if (!(is_post_type_archive('product') || is_shop() || is_product_taxonomy() || is_product_category() || is_product_tag() || (function_exists('is_product') && !is_product() && is_search()))) {
|
| return;
|
| }
|
|
|
| wp_register_script('wcv-capa-video-js', '', [], false, true);
|
| wp_enqueue_script('wcv-capa-video-js');
|
| $js = "
|
| (function(){
|
| var vids = document.querySelectorAll('video.wcv-loop-video');
|
| if(!vids.length) return;
|
|
|
| function pauseReset(v){
|
| v.pause();
|
| try{ v.currentTime = 0; }catch(e){}
|
| }
|
|
|
| if('IntersectionObserver' in window){
|
| var io = new IntersectionObserver(function(entries){
|
| entries.forEach(function(entry){
|
| var v = entry.target;
|
| var visible = entry.intersectionRatio >= 0.6;
|
| if(visible){
|
| v.play().catch(function(){});
|
| }else{
|
| pauseReset(v);
|
| }
|
| });
|
| }, {root:null, rootMargin:'0px', threshold:[0,0.6,1]});
|
| vids.forEach(function(v){ io.observe(v); });
|
| } else {
|
| // Fallback leve para navegadores sem IntersectionObserver
|
| function rectRatio(el){
|
| var r = el.getBoundingClientRect();
|
| var vw = window.innerWidth || document.documentElement.clientWidth;
|
| var vh = window.innerHeight || document.documentElement.clientHeight;
|
| var w = Math.max(0, Math.min(r.right, vw) - Math.max(r.left, 0));
|
| var h = Math.max(0, Math.min(r.bottom, vh) - Math.max(r.top, 0));
|
| var interArea = w * h;
|
| var area = (r.width * r.height) || 1;
|
| return interArea / area;
|
| }
|
| function onScroll(){
|
| vids.forEach(function(v){
|
| if(rectRatio(v) >= 0.6){
|
| v.play().catch(function(){});
|
| }else{
|
| pauseReset(v);
|
| }
|
| });
|
| }
|
| ['scroll','resize','orientationchange'].forEach(function(evt){
|
| window.addEventListener(evt, onScroll, {passive:true});
|
| });
|
| onScroll();
|
| }
|
| })();
|
| ";
|
| wp_add_inline_script('wcv-capa-video-js', $js);
|
| }
|
|
|
| private function get_video_attachment_id($product_id) {
|
| return (int) get_post_meta($product_id, self::META_KEY_ID, true);
|
| }
|
|
|
|
|
|
|
| public function replace_main_image_html($html, $post_id) {
|
| if (!function_exists('wc_get_product')) return $html;
|
| $product = wc_get_product($post_id);
|
| if (!$product) return $html;
|
|
|
| $att_id = $this->get_video_attachment_id($product->get_id());
|
| if (!$att_id) return $html;
|
|
|
| $video_url = wp_get_attachment_url($att_id);
|
| if (!$video_url) return $html;
|
|
|
| $mime = get_post_mime_type($att_id);
|
| $poster_id = $product->get_image_id();
|
| $poster_url = $poster_id ? wp_get_attachment_image_url($poster_id, 'full') : '';
|
|
|
| if ($mime === 'image/gif') {
|
| $gif_html = wp_get_attachment_image($att_id, 'full', false, [
|
| 'class' => 'wp-post-image skip-lazy',
|
| 'alt' => $product->get_name(),
|
| ]);
|
| return '<div class="woocommerce-product-gallery__image wcv-video-wrapper">'.$gif_html.'</div>';
|
| }
|
|
|
| $sources = '';
|
| if ($mime === 'video/mp4') {
|
| $sources .= '<source src="'.esc_url($video_url).'?v2" type="video/mp4">';
|
| } elseif ($mime === 'video/webm') {
|
| $sources .= '<source src="'.esc_url($video_url).'" type="video/webm">';
|
| } else {
|
| $sources .= '<source src="'.esc_url($video_url).'">';
|
| }
|
|
|
| $poster_attr = $poster_url ? ' poster="'.esc_url($poster_url).'"' : '';
|
| $video = '<video class="wp-post-image wcv-video skip-lazy" playsinline muted loop autoplay preload="metadata"'.$poster_attr.'>'.$sources.'</video>';
|
|
|
| return '<div class="woocommerce-product-gallery__image wcv-video-wrapper">'.$video.'</div>';
|
| }
|
|
|
| public function maybe_replace_featured_in_gallery($html, $attachment_id) {
|
| if (!is_product()) return $html;
|
| if (!function_exists('wc_get_product')) return $html;
|
| global $product;
|
| if (!$product) return $html;
|
|
|
| $video_att = $this->get_video_attachment_id($product->get_id());
|
| if (!$video_att) return $html;
|
|
|
| $featured_id = $product->get_image_id();
|
| if (!$featured_id || (int)$attachment_id !== (int)$featured_id) return $html;
|
|
|
| return $this->replace_main_image_html($html, $product->get_id());
|
| }
|
|
|
|
|
|
|
| public function replace_loop_thumbnail($html, $size = null, $attr = [], $product = null) {
|
| if (!function_exists('wc_get_product')) return $html;
|
|
|
| if (!$product instanceof WC_Product) {
|
| $product = wc_get_product(get_the_ID());
|
| }
|
| if (!$product) return $html;
|
|
|
| $att_id = $this->get_video_attachment_id($product->get_id());
|
| if (!$att_id) return $html;
|
|
|
| $mime = get_post_mime_type($att_id);
|
| $video_url = wp_get_attachment_url($att_id);
|
| if (!$video_url) return $html;
|
|
|
|
|
| if (!$size) {
|
| $size = apply_filters('single_product_archive_thumbnail_size', 'woocommerce_thumbnail');
|
| }
|
|
|
|
|
| if ($mime === 'image/gif') {
|
| return wp_get_attachment_image($att_id, $size, false, [
|
| 'class' => 'attachment-woocommerce_thumbnail size-woocommerce_thumbnail skip-lazy',
|
| 'alt' => $product->get_name(),
|
| ]);
|
| }
|
|
|
|
|
| $poster_id = $product->get_image_id();
|
| $poster_url = $poster_id ? wp_get_attachment_image_url($poster_id, $size) : '';
|
|
|
| $type = ($mime === 'video/mp4') ? 'video/mp4' : (($mime === 'video/webm') ? 'video/webm' : '');
|
| $poster_attr = $poster_url ? ' poster="'.esc_url($poster_url).'"' : '';
|
|
|
|
|
| $video = '<video class="wcv-loop-video skip-lazy" muted playsinline loop preload="metadata"'.$poster_attr.'>'
|
| . '<source src="'.esc_url($video_url).'"'.($type ? ' type="'.esc_attr($type).'"' : '').'>'
|
| . '</video>';
|
|
|
| return '<span class="wcv-video-thumb-wrapper">'.$video.'</span>';
|
| }
|
| }
|
|
|
| add_action('plugins_loaded', function(){
|
| if (class_exists('WooCommerce')) {
|
| new WCV_Capa_Video_Flatsome();
|
| }
|
| });
|
| |
| |
Comments