| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Server-side rendering of the `core/template-part` block. 4 * 5 * @package WordPress 6 */ 7 8 /** 9 * Renders the `core/template-part` block on the server. 10 * 11 * @since 5.9.0 12 * 13 * @global WP_Embed $wp_embed WordPress Embed object. 14 * 15 * @param array $attributes The block attributes. 16 * 17 * @return string The render. 18 */ 19 function render_block_core_template_part( $attributes ) { 20 static $seen_ids = array(); 21 22 $template_part_id = null; 23 $content = null; 24 $area = WP_TEMPLATE_PART_AREA_UNCATEGORIZED; 25 $theme = $attributes['theme'] ?? get_stylesheet(); 26 27 if ( isset( $attributes['slug'] ) && get_stylesheet() === $theme ) { 28 $template_part_id = $theme . '//' . $attributes['slug']; 29 $template_part_query = new WP_Query( 30 array( 31 'post_type' => 'wp_template_part', 32 'post_status' => 'publish', 33 'post_name__in' => array( $attributes['slug'] ), 34 'tax_query' => array( 35 array( 36 'taxonomy' => 'wp_theme', 37 'field' => 'name', 38 'terms' => $theme, 39 ), 40 ), 41 'posts_per_page' => 1, 42 'no_found_rows' => true, 43 'lazy_load_term_meta' => false, // Do not lazy load term meta, as template parts only have one term. 44 ) 45 ); 46 $template_part_post = $template_part_query->have_posts() ? $template_part_query->next_post() : null; 47 $block_template = $template_part_post ? _build_block_template_result_from_post( $template_part_post ) : null; 48 // Can be a WP_Error if the post's `wp_theme` terms can't be read, even though the query 49 // matched on them. Report it and fall back to the theme file. 50 if ( is_wp_error( $block_template ) ) { 51 wp_trigger_error( 52 __FUNCTION__, 53 sprintf( 54 /* translators: 1: Template part ID, 2: Error message. */ 55 __( 'Error loading the template part %1$s from the database: %2$s' ), 56 $template_part_id, 57 $block_template->get_error_message() 58 ) 59 ); 60 } 61 if ( $block_template && ! is_wp_error( $block_template ) ) { 62 // A published post might already exist if this template part was customized elsewhere 63 // or if it's part of a customized template. 64 $content = $block_template->content; 65 if ( isset( $block_template->area ) ) { 66 $area = $block_template->area; 67 } 68 /** 69 * Fires when a block template part is loaded from a template post stored in the database. 70 * 71 * @since 5.9.0 72 * 73 * @param string $template_part_id The requested template part namespaced to the theme. 74 * @param array $attributes The block attributes. 75 * @param WP_Post $template_part_post The template part post object. 76 * @param string $content The template part content. 77 */ 78 do_action( 'render_block_core_template_part_post', $template_part_id, $attributes, $template_part_post, $content ); 79 } else { 80 $template_part_file_path = ''; 81 // Else, if the template part was provided by the active theme, 82 // render the corresponding file content. 83 if ( 0 === validate_file( $attributes['slug'] ) ) { 84 $block_template = get_block_file_template( $template_part_id, 'wp_template_part' ); 85 86 if ( isset( $block_template->content ) ) { 87 $content = $block_template->content; 88 } 89 if ( isset( $block_template->area ) ) { 90 $area = $block_template->area; 91 } 92 93 // Needed for the `render_block_core_template_part_file` and `render_block_core_template_part_none` actions below. 94 $block_template_file = _get_block_template_file( 'wp_template_part', $attributes['slug'] ); 95 if ( $block_template_file ) { 96 $template_part_file_path = $block_template_file['path']; 97 } 98 } 99 100 if ( '' !== $content && null !== $content ) { 101 /** 102 * Fires when a block template part is loaded from a template part in the theme. 103 * 104 * @since 5.9.0 105 * 106 * @param string $template_part_id The requested template part namespaced to the theme. 107 * @param array $attributes The block attributes. 108 * @param string $template_part_file_path Absolute path to the template path. 109 * @param string $content The template part content. 110 */ 111 do_action( 'render_block_core_template_part_file', $template_part_id, $attributes, $template_part_file_path, $content ); 112 } else { 113 /** 114 * Fires when a requested block template part does not exist in the database nor in the theme. 115 * 116 * @since 5.9.0 117 * 118 * @param string $template_part_id The requested template part namespaced to the theme. 119 * @param array $attributes The block attributes. 120 * @param string $template_part_file_path Absolute path to the not found template path. 121 */ 122 do_action( 'render_block_core_template_part_none', $template_part_id, $attributes, $template_part_file_path ); 123 } 124 } 125 } 126 127 // WP_DEBUG_DISPLAY must only be honored when WP_DEBUG. This precedent 128 // is set in `wp_debug_mode()`. 129 $is_debug = WP_DEBUG && WP_DEBUG_DISPLAY; 130 131 if ( is_null( $content ) ) { 132 if ( $is_debug && isset( $attributes['slug'] ) ) { 133 return sprintf( 134 /* translators: %s: Template part slug. */ 135 __( 'Template part has been deleted or is unavailable: %s' ), 136 $attributes['slug'] 137 ); 138 } 139 140 return ''; 141 } 142 143 if ( isset( $seen_ids[ $template_part_id ] ) ) { 144 return $is_debug ? 145 // translators: Visible only in the front end, this warning takes the place of a faulty block. 146 __( '[block rendering halted]' ) : 147 ''; 148 } 149 150 // Look up area definition. 151 $area_definition = null; 152 $defined_areas = get_allowed_block_template_part_areas(); 153 foreach ( $defined_areas as $defined_area ) { 154 if ( $defined_area['area'] === $area ) { 155 $area_definition = $defined_area; 156 break; 157 } 158 } 159 160 // If $area is not allowed, set it back to the uncategorized default. 161 if ( ! $area_definition ) { 162 $area = WP_TEMPLATE_PART_AREA_UNCATEGORIZED; 163 } 164 165 // Run through the actions that are typically taken on the_content. 166 $content = _wp_apply_block_content_filters( $content, "template_part_{$area}", $seen_ids, $template_part_id ); 167 168 $tag_name = $attributes['tagName'] ?? null; 169 if ( empty( $tag_name ) || ! is_string( $tag_name ) || tag_escape( $tag_name ) !== $tag_name ) { 170 $area_tag = 'div'; 171 if ( $area_definition && isset( $area_definition['area_tag'] ) ) { 172 $area_tag = $area_definition['area_tag']; 173 } 174 $html_tag = $area_tag; 175 } else { 176 $html_tag = esc_attr( $attributes['tagName'] ); 177 } 178 $wrapper_attributes = get_block_wrapper_attributes(); 179 180 return "<$html_tag $wrapper_attributes>" . str_replace( ']]>', ']]>', $content ) . "</$html_tag>"; 181 } 182 183 /** 184 * Returns an array of area variation objects for the template part block. 185 * 186 * @since 6.1.0 187 * 188 * @param array $instance_variations The variations for instances. 189 * 190 * @return array Array containing the block variation objects. 191 */ 192 function build_template_part_block_area_variations( $instance_variations ) { 193 $variations = array(); 194 $defined_areas = get_allowed_block_template_part_areas(); 195 196 foreach ( $defined_areas as $area ) { 197 if ( 'uncategorized' !== $area['area'] && 'navigation-overlay' !== $area['area'] ) { 198 $has_instance_for_area = false; 199 foreach ( $instance_variations as $variation ) { 200 if ( $variation['attributes']['area'] === $area['area'] ) { 201 $has_instance_for_area = true; 202 break; 203 } 204 } 205 206 $scope = $has_instance_for_area ? array() : array( 'inserter' ); 207 208 $variations[] = array( 209 'name' => 'area_' . $area['area'], 210 'title' => $area['label'], 211 'description' => $area['description'], 212 'attributes' => array( 213 'area' => $area['area'], 214 ), 215 'scope' => $scope, 216 'icon' => $area['icon'], 217 ); 218 } 219 } 220 return $variations; 221 } 222 223 /** 224 * Returns an array of instance variation objects for the template part block 225 * 226 * @since 6.1.0 227 * 228 * @return array Array containing the block variation objects. 229 */ 230 function build_template_part_block_instance_variations() { 231 // Block themes are unavailable during installation. 232 if ( wp_installing() ) { 233 return array(); 234 } 235 236 if ( ! current_theme_supports( 'block-templates' ) && ! current_theme_supports( 'block-template-parts' ) ) { 237 return array(); 238 } 239 240 $variations = array(); 241 $template_parts = get_block_templates( 242 array( 243 'post_type' => 'wp_template_part', 244 ), 245 'wp_template_part' 246 ); 247 248 $defined_areas = get_allowed_block_template_part_areas(); 249 $icon_by_area = array_combine( array_column( $defined_areas, 'area' ), array_column( $defined_areas, 'icon' ) ); 250 251 foreach ( $template_parts as $template_part ) { 252 // Navigation overlay template parts should not appear in the 253 // general inserter. They are managed through the Navigation 254 // block's overlay template part selector. 255 $scope = ( 'navigation-overlay' === $template_part->area ) 256 ? array() 257 : array( 'inserter' ); 258 259 $variations[] = array( 260 'name' => 'instance_' . sanitize_title( $template_part->slug ), 261 'title' => $template_part->title, 262 // If there's no description for the template part don't show the 263 // block description. This is a bit hacky, but prevent the fallback 264 // by using a non-breaking space so that the value of description 265 // isn't falsey. 266 'description' => $template_part->description || ' ', 267 'attributes' => array( 268 'slug' => $template_part->slug, 269 'theme' => $template_part->theme, 270 'area' => $template_part->area, 271 ), 272 'scope' => $scope, 273 'icon' => $icon_by_area[ $template_part->area ] ?? null, 274 'example' => array( 275 'attributes' => array( 276 'slug' => $template_part->slug, 277 'theme' => $template_part->theme, 278 'area' => $template_part->area, 279 ), 280 ), 281 ); 282 } 283 return $variations; 284 } 285 286 /** 287 * Returns an array of all template part block variations. 288 * 289 * @since 5.9.0 290 * 291 * @return array Array containing the block variation objects. 292 */ 293 function build_template_part_block_variations() { 294 $instance_variations = build_template_part_block_instance_variations(); 295 $area_variations = build_template_part_block_area_variations( $instance_variations ); 296 return array_merge( $area_variations, $instance_variations ); 297 } 298 299 /** 300 * Registers the `core/template-part` block on the server. 301 * 302 * @since 5.9.0 303 */ 304 function register_block_core_template_part() { 305 register_block_type_from_metadata( 306 __DIR__ . '/template-part', 307 array( 308 'render_callback' => 'render_block_core_template_part', 309 'variation_callback' => 'build_template_part_block_variations', 310 ) 311 ); 312 } 313 add_action( 'init', 'register_block_core_template_part' );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Sun Nov 1 08:20:35 2026 | Cross-referenced by PHPXref |