Jake Vanderwerf
2025-10-01 37178128edb71f07c346d9e9670eb761d98947ae
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<?php
namespace JVBase\blocks;
 
if (!defined('ABSPATH')) {
    exit;
}
 
/**
 * Video Cover Block Class
 *
 * Handles registration and rendering of self-hosted video cover blocks
 * with poster images and multiple video format support
 */
class VideoCoverBlock
{
    protected static ?VideoCoverBlock $instance = null;
    protected string $path = JVB_DIR . '/build/video-cover';
 
    public static function getInstance(): VideoCoverBlock
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
 
    public function __construct()
    {
        add_action('init', [$this, 'registerBlock']);
    }
 
    public function registerBlock(): void
    {
        register_block_type($this->path, [
            'render_callback' => [$this, 'render']
        ]);
    }
 
    /**
     * Render the video cover block
     */
    public function render($attributes, $content): string
    {
        // Extract attributes with defaults
        $poster_id = $attributes['posterId'] ?? 0;
        $video_sources = $attributes['videoSources'] ?? [];
        $mobile_sources = $attributes['mobileSources'] ?? [];
        $css_class = $attributes['className'] ?? '';
        $fade_class = $attributes['fadeEffect'] ?? false ? 'fade' : '';
        //Get date of current post
        global $post;
        $date = date('c',strtotime($post->post_date));
        $title = $attributes['title'] ?? $post->post_title;
        $description = $attributes['description'] ?? $post->post_excerpt;
 
        // If no video sources, return empty
        if (empty($video_sources)) {
            return '';
        }
 
 
 
        // Get poster URL
        $poster_url = $poster_id ? wp_get_attachment_url($poster_id) : '';
 
        // Build video tag
        $classes = trim("video-cover {$fade_class} {$css_class}");
 
        $html = '<section class="'.esc_attr($classes).'">
        <script type="application/ld+json">
        {
            "@context": "https://schema.org/",
            "@type": "VideoObject",
            "name": "'.$title.'",
            "thumbnailUrl": "'.$poster_url.'",
            "contentUrl": "'.$video_sources[0]['url'].'",
            "description": "'.$description.'",
            "uploadDate": "'.$date.'"
        }
    </script>
    <div class="wrap">
        <div class="video-container">';
        $html .= '<video';
        $html .= ' muted loop playsinline autoplay';
 
        if ($poster_url) {
            $html .= ' poster="' . esc_url($poster_url) . '"';
        }
 
        $html .= '>';
 
        // Add mobile sources first (lower resolution)
        foreach ($mobile_sources as $source) {
            if (!empty($source['url']) && !empty($source['mime'])) {
                $html .= '<source';
                $html .= ' src="' . esc_url($source['url']) . '"';
                $html .= ' type="' . esc_attr($source['mime']) . '"';
                $html .= ' media="(max-width: 767px)"';
                $html .= '>';
            }
        }
 
        // Add desktop sources
        foreach ($video_sources as $source) {
            if (!empty($source['url']) && !empty($source['mime'])) {
                $html .= '<source';
                $html .= ' src="' . esc_url($source['url']) . '"';
                $html .= ' type="' . esc_attr($source['mime']) . '"';
 
                // Add media query for desktop if mobile sources exist
                if (!empty($mobile_sources)) {
                    $html .= ' media="(min-width: 768px)"';
                }
 
                $html .= '>';
            }
        }
 
        $html .= '</video>';
        $html .= '</div></div><div class="inner-wrap"></div></section>';
 
        return $html;
    }
}