get_all_registered(), 'slug' ); foreach ( $categories as $category => $patterns ) { if ( ! in_array( $category, $registered_categories, true ) ) { if ( in_array( $category, [ 'cta', 'faq' ], true ) ) { $label = strtoupper( $category ); } else { $label = ucwords( str_replace( '-', ' ', $category ) ); } register_block_pattern_category( $category, [ 'label' => $label, ] ); $registered_categories[ $category ] = []; } foreach ( $patterns as $pattern => $file ) { $basename = basename( $file, '.php' ); if ( in_array( $basename, $registered_categories[ $category ], true ) ) { continue; } $slug = $category . '-' . $basename; if ( in_array( $slug, $registered_slugs, true ) ) { continue; } register_block_pattern_from_file( $file ); $registered_categories[ $category ][] = $basename; } } } /** * Parses a pattern file and returns the pattern data. * * @since 0.0.2 * * @param string $file The file path. * * @return array */ function parse_pattern_file( string $file ): array { if ( ! $file ) { return []; } $content = ''; $default_headers = [ 'categories' => 'Categories', 'title' => 'Title', 'slug' => 'Slug', 'block_types' => 'Block Types', 'inserter' => 'Inserter', 'ID' => 'ID', 'theme' => 'Theme', ]; if ( is_readable( $file ) ) { $headers = get_file_data( $file, $default_headers ); ob_start(); $global_settings = wp_get_global_settings(); include $file; $content = ob_get_clean(); } else { if ( str_contains( $file, 'Title: ' ) ) { $content = $file; $headers = $default_headers; // Use regex from get_file_data(). foreach ( $headers as $field => $regex ) { if ( preg_match( '/^(?:[ \t]*<\?php)?[ \t\/*#@]*' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $file, $match ) && $match[1] ) { $headers[ $field ] = _cleanup_header_comment( $match[1] ); } else { $headers[ $field ] = ''; } } } } if ( ! isset( $headers['title'], $headers['slug'], $headers['categories'] ) ) { return []; } $categories = explode( ',', $headers['categories'] ); $theme = $headers['theme'] ?? null; if ( ! $theme ) { $stylesheet_dir = get_stylesheet_directory(); $template_dir = get_template_directory(); if ( $stylesheet_dir === $template_dir ) { $theme = get_template(); } else if ( str_contains( $file, $stylesheet_dir ) ) { $theme = get_stylesheet(); } else if ( str_contains( $file, $template_dir ) ) { $theme = get_template(); } } $pattern = [ 'slug' => $categories[0] . '-' . $headers['slug'], 'title' => $headers['title'], 'content' => str_replace_first( str_between( '', $content ), '', $content ), 'categories' => [ ...$categories ], 'description' => $headers['description'] ?? '', 'viewportWidth' => $headers['viewport_width'] ?? null, 'blockTypes' => $headers['block_types'] ?? [], 'ID' => $headers['ID'] ?? null, 'theme' => $theme, ]; if ( ( $headers['inserter'] ?? null ) === 'false' ) { $pattern['inserter'] = false; } return $pattern; } /** * Parses and registers block pattern from PHP file with header comment. * * @since 0.0.8 * * @param string $file Path to PHP file or content. * * @return void */ function register_block_pattern_from_file( string $file ): void { $pattern = parse_pattern_file( $file ); foreach ( ( $pattern['categories'] ?? [] ) as $category ) { if ( in_array( $category, [ 'cta', 'faq' ], true ) ) { $label = strtoupper( $category ); } else { $label = ucwords( str_replace( '-', ' ', $category ) ); } register_block_pattern_category( $category, [ 'label' => $label, ] ); } register_block_pattern( $pattern['slug'], $pattern ); } /** * Get block HTML. * * @since 1.3.0 * * @param array $block Block. * @param bool $render Whether to render the block. * * @return string */ function get_block_html( array $block, bool $render = false ): string { $block['innerContent'] = $block['innerContent'] ?? []; $block['innerHTML'] = $block['innerHTML'] ?? ''; $block['innerBlocks'] = $block['innerBlocks'] ?? []; $name = strip_core_block_namespace( $block['blockName'] ?? '' ); if ( ! $name || empty( $block['innerBlocks'] ) ) { return serialize_block( $block ); } $classes = array_filter( [ 'wp-block-' . $name, $block['attrs']['className'] ?? null, isset( $block['attrs']['fontSize'] ) ? 'has-' . $block['attrs']['fontSize'] . '-font-size' : null, isset( $block['attrs']['textColor'] ) ? 'has-' . $block['attrs']['textColor'] . '-color' : null, isset( $block['attrs']['backgroundColor'] ) ? 'has-' . $block['attrs']['backgroundColor'] . '-background-color' : null, ] ); $styles = array_filter( [ 'gap' => $block['attrs']['style']['spacing']['blockGap'] ?? null, ] ); $tag = $block['tagName'] ?? $block['attrs']['tagName'] ?? 'div'; $opening = sprintf( '<%s class="%s" style="%s">', $tag, implode( ' ', $classes ), css_array_to_string( $styles ) ); $closing = sprintf( '', $tag ); $inner_content = $block['innerContent']; array_unshift( $inner_content, $opening ); $inner_content[] = $closing; foreach ( $block['innerBlocks'] as $inner_block ) { $inner_content[] = get_block_html( $inner_block ); } $block['innerContent'] = $inner_content; $block['innerHTML'] = implode( '', $inner_content ); $serialized = serialize_block( $block ); $parsed_block = parse_blocks( $serialized )[0]; return $render ? render_block( $parsed_block ) : $serialized; }