PluginProbe
Gutenberg / 23.7.2
Gutenberg v23.7.2
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 23.7.2, at build/scripts/block-library/cover.php

223 lines 7.7 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 $cover_focal_point = $attributes['focalPoint'] ?? null;
138 $focal_point_x = null;
139 $focal_point_y = null;
140 if ( is_array( $cover_focal_point ) ) {
141 $focal_point_x = isset( $cover_focal_point['x'] ) && is_numeric( $cover_focal_point['x'] ) ? $cover_focal_point['x'] : null;
142 $focal_point_y = isset( $cover_focal_point['y'] ) && is_numeric( $cover_focal_point['y'] ) ? $cover_focal_point['y'] : null;
143 }
144 $object_position = null !== $focal_point_x && null !== $focal_point_y
145 ? round( $focal_point_x * 100 ) . '% ' . round( $focal_point_y * 100 ) . '%'
146 : null;
147
148 if ( ! ( $attributes['hasParallax'] || $attributes['isRepeated'] ) ) {
149 $attr = array(
150 'class' => 'wp-block-cover__image-background',
151 'data-object-fit' => 'cover',
152 );
153
154 if ( $object_position ) {
155 $attr['data-object-position'] = $object_position;
156 $attr['style'] = 'object-position:' . $object_position . ';';
157 }
158
159 $image = get_the_post_thumbnail( null, $attributes['sizeSlug'] ?? 'post-thumbnail', $attr );
160 } else {
161 if ( in_the_loop() ) {
162 update_post_thumbnail_cache();
163 }
164 $current_featured_image = get_the_post_thumbnail_url( null, $attributes['sizeSlug'] ?? null );
165 if ( ! $current_featured_image ) {
166 return $content;
167 }
168
169 $current_thumbnail_id = get_post_thumbnail_id();
170
171 $processor = new WP_HTML_Tag_Processor( '<div></div>' );
172 $processor->next_tag();
173
174 $current_alt = trim( strip_tags( get_post_meta( $current_thumbnail_id, '_wp_attachment_image_alt', true ) ) );
175 if ( $current_alt ) {
176 $processor->set_attribute( 'role', 'img' );
177 $processor->set_attribute( 'aria-label', $current_alt );
178 }
179
180 $processor->add_class( 'wp-block-cover__image-background' );
181 $processor->add_class( 'wp-image-' . $current_thumbnail_id );
182 if ( $attributes['hasParallax'] ) {
183 $processor->add_class( 'has-parallax' );
184 }
185 if ( $attributes['isRepeated'] ) {
186 $processor->add_class( 'is-repeated' );
187 }
188
189 $styles = 'background-position:' . ( $object_position ?? '50% 50%' ) . ';';
190 $styles .= 'background-image:url(' . esc_url( $current_featured_image ) . ');';
191 $processor->set_attribute( 'style', $styles );
192
193 $image = $processor->get_updated_html();
194 }
195
196 /*
197 * Inserts the featured image between the (1st) cover 'background' `span` and 'inner_container' `div`,
198 * and removes eventual whitespace characters between the two (typically introduced at template level)
199 */
200 $inner_container_start = '/<div\b[^>]+wp-block-cover__inner-container[\s|"][^>]*>/U';
201 if ( 1 === preg_match( $inner_container_start, $content, $matches, PREG_OFFSET_CAPTURE ) ) {
202 $offset = $matches[0][1];
203 $content = substr( $content, 0, $offset ) . $image . substr( $content, $offset );
204 }
205
206 return $content;
207 }
208
209 /**
210 * Registers the `core/cover` block renderer on server.
211 *
212 * @since 6.0.0
213 */
214 function gutenberg_register_block_core_cover() {
215 register_block_type_from_metadata(
216 __DIR__ . '/cover',
217 array(
218 'render_callback' => 'gutenberg_render_block_core_cover',
219 )
220 );
221 }
222 add_action( 'init', 'gutenberg_register_block_core_cover', 20 );
223