PluginProbe
Gutenberg / 22.9.0
Gutenberg v22.9.0
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / build / scripts / block-library / cover.php

cover.php in Gutenberg 22.9.0, at build/scripts/block-library/cover.php

216 lines 7.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Server-side rendering of the `core/cover` block.
4 *
5 * @package WordPress
6 */
7
8 /**
9 * Renders the `core/cover` block on server.
10 *
11 * @since 6.0.0
12 *
13 * @param array $attributes The block attributes.
14 * @param string $content The block rendered content.
15 *
16 * @return string Returns the cover block markup, if useFeaturedImage is true.
17 */
18 function gutenberg_render_block_core_cover( $attributes, $content ) {
19 // Handle embed video background.
20 if (
21 isset( $attributes['backgroundType'] ) &&
22 'embed-video' === $attributes['backgroundType'] &&
23 isset( $attributes['url'] ) &&
24 ! empty( $attributes['url'] ) &&
25 is_string( $attributes['url'] )
26 ) {
27 $url = $attributes['url'];
28
29 // Use WordPress's native oEmbed processing (includes caching).
30 $oembed_html = wp_oembed_get( $url );
31
32 if ( $oembed_html ) {
33 // Extract iframe src from the oEmbed HTML.
34 preg_match( '/src=["\']([^"\']+)["\']/', $oembed_html, $src_matches );
35 if ( ! empty( $src_matches[1] ) ) {
36 $iframe_src = $src_matches[1];
37
38 // Detect provider from iframe src URL.
39 $lower_src = strtolower( $iframe_src );
40 $provider = null;
41
42 if ( str_contains( $lower_src, 'youtube.com' ) || str_contains( $lower_src, 'youtu.be' ) ) {
43 $provider = 'youtube';
44 } elseif ( str_contains( $lower_src, 'vimeo.com' ) ) {
45 $provider = 'vimeo';
46 } elseif ( str_contains( $lower_src, 'videopress.com' ) ) {
47 $provider = 'videopress';
48 } elseif ( str_contains( $lower_src, 'wordpress.tv' ) ) {
49 $provider = 'wordpress-tv';
50 }
51
52 // Modify iframe src to add background video parameters based on provider.
53 $parsed_url = wp_parse_url( $iframe_src );
54 if ( $parsed_url && isset( $parsed_url['host'] ) ) {
55 // Parse existing query parameters.
56 $query_params = array();
57 if ( isset( $parsed_url['query'] ) ) {
58 parse_str( $parsed_url['query'], $query_params );
59 }
60
61 // Add background video parameters based on provider.
62 if ( 'youtube' === $provider ) {
63 $query_params['autoplay'] = '1';
64 $query_params['mute'] = '1';
65 $query_params['loop'] = '1';
66 $query_params['controls'] = '0';
67 $query_params['modestbranding'] = '1';
68 $query_params['playsinline'] = '1';
69
70 // For loop to work, we need the playlist parameter.
71 $path = $parsed_url['path'] ?? '';
72 $path_segments = explode( '/', $path );
73 $video_id = end( $path_segments );
74 if ( $video_id ) {
75 $query_params['playlist'] = $video_id;
76 }
77 } elseif ( 'vimeo' === $provider ) {
78 $query_params['autoplay'] = '1';
79 $query_params['muted'] = '1';
80 $query_params['loop'] = '1';
81 $query_params['background'] = '1';
82 $query_params['controls'] = '0';
83 $query_params['transparent'] = '0';
84 } elseif ( 'videopress' === $provider || 'wordpress-tv' === $provider ) {
85 $query_params['autoplay'] = '1';
86 $query_params['loop'] = '1';
87 $query_params['muted'] = '1';
88 }
89
90 // Rebuild the URL with new parameters.
91 $iframe_src = $parsed_url['scheme'] . '://' . $parsed_url['host'];
92 if ( isset( $parsed_url['path'] ) ) {
93 $iframe_src .= $parsed_url['path'];
94 }
95 if ( ! empty( $query_params ) ) {
96 $iframe_src .= '?' . http_build_query( $query_params );
97 }
98 }
99
100 // Build the iframe HTML that will replace the figure.
101 $iframe_html = sprintf(
102 '<div class="wp-block-cover__video-background wp-block-cover__embed-background"><iframe src="%s" title="Background video" frameborder="0" allow="autoplay; fullscreen"></iframe></div>',
103 esc_url( $iframe_src )
104 );
105
106 // Use the HTML API to find and replace the figure.wp-block-embed element.
107 $processor = new WP_HTML_Tag_Processor( $content );
108
109 if ( $processor->next_tag(
110 array(
111 'tag_name' => 'FIGURE',
112 'class_name' => 'wp-block-embed',
113 )
114 ) ) {
115 // Use regex with PREG_OFFSET_CAPTURE to find the position of the figure element.
116 // This follows the same pattern used for featured image insertion below.
117 $figure_pattern = '/<figure\s+[^>]*\bwp-block-embed\b[^>]*>.*?<\/figure>/is';
118 if ( 1 === preg_match( $figure_pattern, $content, $matches, PREG_OFFSET_CAPTURE ) ) {
119 $figure_start = $matches[0][1];
120 $figure_length = strlen( $matches[0][0] );
121 $figure_end = $figure_start + $figure_length;
122
123 // Replace the figure element with the iframe HTML.
124 $content = substr( $content, 0, $figure_start ) . $iframe_html . substr( $content, $figure_end );
125 }
126 }
127 }
128 }
129
130 return $content;
131 }
132
133 if ( 'image' !== $attributes['backgroundType'] || false === $attributes['useFeaturedImage'] ) {
134 return $content;
135 }
136
137 $object_position = isset( $attributes['focalPoint'] )
138 ? round( $attributes['focalPoint']['x'] * 100 ) . '% ' . round( $attributes['focalPoint']['y'] * 100 ) . '%'
139 : null;
140
141 if ( ! ( $attributes['hasParallax'] || $attributes['isRepeated'] ) ) {
142 $attr = array(
143 'class' => 'wp-block-cover__image-background',
144 'data-object-fit' => 'cover',
145 );
146
147 if ( $object_position ) {
148 $attr['data-object-position'] = $object_position;
149 $attr['style'] = 'object-position:' . $object_position . ';';
150 }
151
152 $image = get_the_post_thumbnail( null, $attributes['sizeSlug'] ?? 'post-thumbnail', $attr );
153 } else {
154 if ( in_the_loop() ) {
155 update_post_thumbnail_cache();
156 }
157 $current_featured_image = get_the_post_thumbnail_url( null, $attributes['sizeSlug'] ?? null );
158 if ( ! $current_featured_image ) {
159 return $content;
160 }
161
162 $current_thumbnail_id = get_post_thumbnail_id();
163
164 $processor = new WP_HTML_Tag_Processor( '<div></div>' );
165 $processor->next_tag();
166
167 $current_alt = trim( strip_tags( get_post_meta( $current_thumbnail_id, '_wp_attachment_image_alt', true ) ) );
168 if ( $current_alt ) {
169 $processor->set_attribute( 'role', 'img' );
170 $processor->set_attribute( 'aria-label', $current_alt );
171 }
172
173 $processor->add_class( 'wp-block-cover__image-background' );
174 $processor->add_class( 'wp-image-' . $current_thumbnail_id );
175 if ( $attributes['hasParallax'] ) {
176 $processor->add_class( 'has-parallax' );
177 }
178 if ( $attributes['isRepeated'] ) {
179 $processor->add_class( 'is-repeated' );
180 }
181
182 $styles = 'background-position:' . ( $object_position ?? '50% 50%' ) . ';';
183 $styles .= 'background-image:url(' . esc_url( $current_featured_image ) . ');';
184 $processor->set_attribute( 'style', $styles );
185
186 $image = $processor->get_updated_html();
187 }
188
189 /*
190 * Inserts the featured image between the (1st) cover 'background' `span` and 'inner_container' `div`,
191 * and removes eventual whitespace characters between the two (typically introduced at template level)
192 */
193 $inner_container_start = '/<div\b[^>]+wp-block-cover__inner-container[\s|"][^>]*>/U';
194 if ( 1 === preg_match( $inner_container_start, $content, $matches, PREG_OFFSET_CAPTURE ) ) {
195 $offset = $matches[0][1];
196 $content = substr( $content, 0, $offset ) . $image . substr( $content, $offset );
197 }
198
199 return $content;
200 }
201
202 /**
203 * Registers the `core/cover` block renderer on server.
204 *
205 * @since 6.0.0
206 */
207 function gutenberg_register_block_core_cover() {
208 register_block_type_from_metadata(
209 __DIR__ . '/cover',
210 array(
211 'render_callback' => 'gutenberg_render_block_core_cover',
212 )
213 );
214 }
215 add_action( 'init', 'gutenberg_register_block_core_cover', 20 );
216