_register_theme_block_patterns

The timeline below displays how wordpress function _register_theme_block_patterns has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.5

/**
 * Register any patterns that the active theme may provide under its
 * `./patterns/` directory.
 *
 * @since 6.0.0
 * @since 6.1.0 The `postTypes` property was added.
 * @since 6.2.0 The `templateTypes` property was added.
 * @since 6.4.0 Uses the `WP_Theme::get_block_patterns` method.
 * @access private
 */
function _register_theme_block_patterns()
{
    /*
     * During the bootstrap process, a check for active and valid themes is run.
     * If no themes are returned, the theme's functions.php file will not be loaded,
     * which can lead to errors if patterns expect some variables or constants to
     * already be set at this point, so bail early if that is the case.
     */
    if (empty(wp_get_active_and_valid_themes())) {
        return;
    }
    /*
     * Register patterns for the active theme. If the theme is a child theme,
     * let it override any patterns from the parent theme that shares the same slug.
     */
    $themes = array();
    $theme = wp_get_theme();
    $themes[] = $theme;
    if ($theme->parent()) {
        $themes[] = $theme->parent();
    }
    $registry = WP_Block_Patterns_Registry::get_instance();
    foreach ($themes as $theme) {
        $patterns = $theme->get_block_patterns();
        $dirpath = $theme->get_stylesheet_directory() . '/patterns/';
        $text_domain = $theme->get('TextDomain');
        foreach ($patterns as $file => $pattern_data) {
            if ($registry->is_registered($pattern_data['slug'])) {
                continue;
            }
            $file_path = $dirpath . $file;
            if (!file_exists($file_path)) {
                _doing_it_wrong(__FUNCTION__, sprintf(
                    /* translators: %s: file name. */
                    __('Could not register file "%s" as a block pattern as the file does not exist.'),
                    $file
                ), '6.4.0');
                $theme->delete_pattern_cache();
                continue;
            }
            $pattern_data['filePath'] = $file_path;
            // Translate the pattern metadata.
            // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain,WordPress.WP.I18n.LowLevelTranslationFunction
            $pattern_data['title'] = translate_with_gettext_context($pattern_data['title'], 'Pattern title', $text_domain);
            if (!empty($pattern_data['description'])) {
                // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain,WordPress.WP.I18n.LowLevelTranslationFunction
                $pattern_data['description'] = translate_with_gettext_context($pattern_data['description'], 'Pattern description', $text_domain);
            }
            register_block_pattern($pattern_data['slug'], $pattern_data);
        }
    }
}

WordPress Version: 4.2

/**
 * Register any patterns that the active theme may provide under its
 * `./patterns/` directory.
 *
 * @since 6.0.0
 * @since 6.1.0 The `postTypes` property was added.
 * @since 6.2.0 The `templateTypes` property was added.
 * @since 6.4.0 Uses the `WP_Theme::get_block_patterns` method.
 * @access private
 */
function _register_theme_block_patterns()
{
    /*
     * During the bootstrap process, a check for active and valid themes is run.
     * If no themes are returned, the theme's functions.php file will not be loaded,
     * which can lead to errors if patterns expect some variables or constants to
     * already be set at this point, so bail early if that is the case.
     */
    if (empty(wp_get_active_and_valid_themes())) {
        return;
    }
    /*
     * Register patterns for the active theme. If the theme is a child theme,
     * let it override any patterns from the parent theme that shares the same slug.
     */
    $themes = array();
    $theme = wp_get_theme();
    $themes[] = $theme;
    if ($theme->parent()) {
        $themes[] = $theme->parent();
    }
    $registry = WP_Block_Patterns_Registry::get_instance();
    foreach ($themes as $theme) {
        $patterns = $theme->get_block_patterns();
        $dirpath = $theme->get_stylesheet_directory() . '/patterns/';
        $text_domain = $theme->get('TextDomain');
        foreach ($patterns as $file => $pattern_data) {
            if ($registry->is_registered($pattern_data['slug'])) {
                continue;
            }
            $file_path = $dirpath . $file;
            if (!file_exists($file_path)) {
                _doing_it_wrong(__FUNCTION__, sprintf(
                    /* translators: %s: file name. */
                    __('Could not register file "%s" as a block pattern as the file does not exist.'),
                    $file
                ), '6.4.0');
                $theme->delete_pattern_cache();
                continue;
            }
            // The actual pattern content is the output of the file.
            ob_start();
            include $file_path;
            $pattern_data['content'] = ob_get_clean();
            if (!$pattern_data['content']) {
                continue;
            }
            // Translate the pattern metadata.
            // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain,WordPress.WP.I18n.LowLevelTranslationFunction
            $pattern_data['title'] = translate_with_gettext_context($pattern_data['title'], 'Pattern title', $text_domain);
            if (!empty($pattern_data['description'])) {
                // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain,WordPress.WP.I18n.LowLevelTranslationFunction
                $pattern_data['description'] = translate_with_gettext_context($pattern_data['description'], 'Pattern description', $text_domain);
            }
            register_block_pattern($pattern_data['slug'], $pattern_data);
        }
    }
}

WordPress Version: 6.4

/**
 * Register any patterns that the active theme may provide under its
 * `./patterns/` directory.
 *
 * @since 6.0.0
 * @since 6.1.0 The `postTypes` property was added.
 * @since 6.2.0 The `templateTypes` property was added.
 * @since 6.4.0 Uses the `_wp_get_block_patterns` function.
 * @access private
 */
function _register_theme_block_patterns()
{
    /*
     * During the bootstrap process, a check for active and valid themes is run.
     * If no themes are returned, the theme's functions.php file will not be loaded,
     * which can lead to errors if patterns expect some variables or constants to
     * already be set at this point, so bail early if that is the case.
     */
    if (empty(wp_get_active_and_valid_themes())) {
        return;
    }
    /*
     * Register patterns for the active theme. If the theme is a child theme,
     * let it override any patterns from the parent theme that shares the same slug.
     */
    $themes = array();
    $theme = wp_get_theme();
    $themes[] = $theme;
    if ($theme->parent()) {
        $themes[] = $theme->parent();
    }
    $registry = WP_Block_Patterns_Registry::get_instance();
    foreach ($themes as $theme) {
        $patterns = $theme->get_block_patterns();
        $dirpath = $theme->get_stylesheet_directory() . '/patterns/';
        $text_domain = $theme->get('TextDomain');
        foreach ($patterns as $file => $pattern_data) {
            if ($registry->is_registered($pattern_data['slug'])) {
                continue;
            }
            $file_path = $dirpath . $file;
            if (!file_exists($file_path)) {
                _doing_it_wrong(__FUNCTION__, sprintf(
                    /* translators: %s: file name. */
                    __('Could not register file "%s" as a block pattern as the file does not exist.'),
                    $file
                ), '6.4.0');
                $theme->delete_pattern_cache();
                continue;
            }
            // The actual pattern content is the output of the file.
            ob_start();
            include $file_path;
            $pattern_data['content'] = ob_get_clean();
            if (!$pattern_data['content']) {
                continue;
            }
            // Translate the pattern metadata.
            // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain,WordPress.WP.I18n.LowLevelTranslationFunction
            $pattern_data['title'] = translate_with_gettext_context($pattern_data['title'], 'Pattern title', $text_domain);
            if (!empty($pattern_data['description'])) {
                // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText,WordPress.WP.I18n.NonSingularStringLiteralDomain,WordPress.WP.I18n.LowLevelTranslationFunction
                $pattern_data['description'] = translate_with_gettext_context($pattern_data['description'], 'Pattern description', $text_domain);
            }
            register_block_pattern($pattern_data['slug'], $pattern_data);
        }
    }
}

WordPress Version: 6.2

/**
 * Register any patterns that the active theme may provide under its
 * `./patterns/` directory. Each pattern is defined as a PHP file and defines
 * its metadata using plugin-style headers. The minimum required definition is:
 *
 *     /**
 *      * Title: My Pattern
 *      * Slug: my-theme/my-pattern
 *      *
 *
 * The output of the PHP source corresponds to the content of the pattern, e.g.:
 *
 *     <main><p><?php echo "Hello"; ?></p></main>
 *
 * If applicable, this will collect from both parent and child theme.
 *
 * Other settable fields include:
 *
 *   - Description
 *   - Viewport Width
 *   - Inserter         (yes/no)
 *   - Categories       (comma-separated values)
 *   - Keywords         (comma-separated values)
 *   - Block Types      (comma-separated values)
 *   - Post Types       (comma-separated values)
 *   - Template Types   (comma-separated values)
 *
 * @since 6.0.0
 * @since 6.1.0 The `postTypes` property was added.
 * @since 6.2.0 The `templateTypes` property was added.
 * @access private
 */
function _register_theme_block_patterns()
{
    $default_headers = array('title' => 'Title', 'slug' => 'Slug', 'description' => 'Description', 'viewportWidth' => 'Viewport Width', 'inserter' => 'Inserter', 'categories' => 'Categories', 'keywords' => 'Keywords', 'blockTypes' => 'Block Types', 'postTypes' => 'Post Types', 'templateTypes' => 'Template Types');
    /*
     * Register patterns for the active theme. If the theme is a child theme,
     * let it override any patterns from the parent theme that shares the same slug.
     */
    $themes = array();
    $stylesheet = get_stylesheet();
    $template = get_template();
    if ($stylesheet !== $template) {
        $themes[] = wp_get_theme($stylesheet);
    }
    $themes[] = wp_get_theme($template);
    foreach ($themes as $theme) {
        $dirpath = $theme->get_stylesheet_directory() . '/patterns/';
        if (!is_dir($dirpath) || !is_readable($dirpath)) {
            continue;
        }
        if (file_exists($dirpath)) {
            $files = glob($dirpath . '*.php');
            if ($files) {
                foreach ($files as $file) {
                    $pattern_data = get_file_data($file, $default_headers);
                    if (empty($pattern_data['slug'])) {
                        _doing_it_wrong('_register_theme_block_patterns', sprintf(
                            /* translators: %s: file name. */
                            __('Could not register file "%s" as a block pattern ("Slug" field missing)'),
                            $file
                        ), '6.0.0');
                        continue;
                    }
                    if (!preg_match('/^[A-z0-9\/_-]+$/', $pattern_data['slug'])) {
                        _doing_it_wrong('_register_theme_block_patterns', sprintf(
                            /* translators: %1s: file name; %2s: slug value found. */
                            __('Could not register file "%1$s" as a block pattern (invalid slug "%2$s")'),
                            $file,
                            $pattern_data['slug']
                        ), '6.0.0');
                    }
                    if (WP_Block_Patterns_Registry::get_instance()->is_registered($pattern_data['slug'])) {
                        continue;
                    }
                    // Title is a required property.
                    if (!$pattern_data['title']) {
                        _doing_it_wrong('_register_theme_block_patterns', sprintf(
                            /* translators: %1s: file name; %2s: slug value found. */
                            __('Could not register file "%s" as a block pattern ("Title" field missing)'),
                            $file
                        ), '6.0.0');
                        continue;
                    }
                    // For properties of type array, parse data as comma-separated.
                    foreach (array('categories', 'keywords', 'blockTypes', 'postTypes', 'templateTypes') as $property) {
                        if (!empty($pattern_data[$property])) {
                            $pattern_data[$property] = array_filter(preg_split('/[\s,]+/', (string) $pattern_data[$property]));
                        } else {
                            unset($pattern_data[$property]);
                        }
                    }
                    // Parse properties of type int.
                    foreach (array('viewportWidth') as $property) {
                        if (!empty($pattern_data[$property])) {
                            $pattern_data[$property] = (int) $pattern_data[$property];
                        } else {
                            unset($pattern_data[$property]);
                        }
                    }
                    // Parse properties of type bool.
                    foreach (array('inserter') as $property) {
                        if (!empty($pattern_data[$property])) {
                            $pattern_data[$property] = in_array(strtolower($pattern_data[$property]), array('yes', 'true'), true);
                        } else {
                            unset($pattern_data[$property]);
                        }
                    }
                    // Translate the pattern metadata.
                    $text_domain = $theme->get('TextDomain');
                    //phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText, WordPress.WP.I18n.NonSingularStringLiteralContext, WordPress.WP.I18n.NonSingularStringLiteralDomain, WordPress.WP.I18n.LowLevelTranslationFunction
                    $pattern_data['title'] = translate_with_gettext_context($pattern_data['title'], 'Pattern title', $text_domain);
                    if (!empty($pattern_data['description'])) {
                        //phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText, WordPress.WP.I18n.NonSingularStringLiteralContext, WordPress.WP.I18n.NonSingularStringLiteralDomain, WordPress.WP.I18n.LowLevelTranslationFunction
                        $pattern_data['description'] = translate_with_gettext_context($pattern_data['description'], 'Pattern description', $text_domain);
                    }
                    // The actual pattern content is the output of the file.
                    ob_start();
                    include $file;
                    $pattern_data['content'] = ob_get_clean();
                    if (!$pattern_data['content']) {
                        continue;
                    }
                    register_block_pattern($pattern_data['slug'], $pattern_data);
                }
            }
        }
    }
}

WordPress Version: 6.1

/**
 * Register any patterns that the active theme may provide under its
 * `./patterns/` directory. Each pattern is defined as a PHP file and defines
 * its metadata using plugin-style headers. The minimum required definition is:
 *
 *     /**
 *      * Title: My Pattern
 *      * Slug: my-theme/my-pattern
 *      *
 *
 * The output of the PHP source corresponds to the content of the pattern, e.g.:
 *
 *     <main><p><?php echo "Hello"; ?></p></main>
 *
 * If applicable, this will collect from both parent and child theme.
 *
 * Other settable fields include:
 *
 *   - Description
 *   - Viewport Width
 *   - Categories       (comma-separated values)
 *   - Keywords         (comma-separated values)
 *   - Block Types      (comma-separated values)
 *   - Post Types       (comma-separated values)
 *   - Inserter         (yes/no)
 *
 * @since 6.0.0
 * @access private
 */
function _register_theme_block_patterns()
{
    $default_headers = array('title' => 'Title', 'slug' => 'Slug', 'description' => 'Description', 'viewportWidth' => 'Viewport Width', 'categories' => 'Categories', 'keywords' => 'Keywords', 'blockTypes' => 'Block Types', 'postTypes' => 'Post Types', 'inserter' => 'Inserter');
    /*
     * Register patterns for the active theme. If the theme is a child theme,
     * let it override any patterns from the parent theme that shares the same slug.
     */
    $themes = array();
    $stylesheet = get_stylesheet();
    $template = get_template();
    if ($stylesheet !== $template) {
        $themes[] = wp_get_theme($stylesheet);
    }
    $themes[] = wp_get_theme($template);
    foreach ($themes as $theme) {
        $dirpath = $theme->get_stylesheet_directory() . '/patterns/';
        if (!is_dir($dirpath) || !is_readable($dirpath)) {
            continue;
        }
        if (file_exists($dirpath)) {
            $files = glob($dirpath . '*.php');
            if ($files) {
                foreach ($files as $file) {
                    $pattern_data = get_file_data($file, $default_headers);
                    if (empty($pattern_data['slug'])) {
                        _doing_it_wrong('_register_theme_block_patterns', sprintf(
                            /* translators: %s: file name. */
                            __('Could not register file "%s" as a block pattern ("Slug" field missing)'),
                            $file
                        ), '6.0.0');
                        continue;
                    }
                    if (!preg_match('/^[A-z0-9\/_-]+$/', $pattern_data['slug'])) {
                        _doing_it_wrong('_register_theme_block_patterns', sprintf(
                            /* translators: %1s: file name; %2s: slug value found. */
                            __('Could not register file "%1$s" as a block pattern (invalid slug "%2$s")'),
                            $file,
                            $pattern_data['slug']
                        ), '6.0.0');
                    }
                    if (WP_Block_Patterns_Registry::get_instance()->is_registered($pattern_data['slug'])) {
                        continue;
                    }
                    // Title is a required property.
                    if (!$pattern_data['title']) {
                        _doing_it_wrong('_register_theme_block_patterns', sprintf(
                            /* translators: %1s: file name; %2s: slug value found. */
                            __('Could not register file "%s" as a block pattern ("Title" field missing)'),
                            $file
                        ), '6.0.0');
                        continue;
                    }
                    // For properties of type array, parse data as comma-separated.
                    foreach (array('categories', 'keywords', 'blockTypes', 'postTypes') as $property) {
                        if (!empty($pattern_data[$property])) {
                            $pattern_data[$property] = array_filter(preg_split('/[\s,]+/', (string) $pattern_data[$property]));
                        } else {
                            unset($pattern_data[$property]);
                        }
                    }
                    // Parse properties of type int.
                    foreach (array('viewportWidth') as $property) {
                        if (!empty($pattern_data[$property])) {
                            $pattern_data[$property] = (int) $pattern_data[$property];
                        } else {
                            unset($pattern_data[$property]);
                        }
                    }
                    // Parse properties of type bool.
                    foreach (array('inserter') as $property) {
                        if (!empty($pattern_data[$property])) {
                            $pattern_data[$property] = in_array(strtolower($pattern_data[$property]), array('yes', 'true'), true);
                        } else {
                            unset($pattern_data[$property]);
                        }
                    }
                    // Translate the pattern metadata.
                    $text_domain = $theme->get('TextDomain');
                    //phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText, WordPress.WP.I18n.NonSingularStringLiteralContext, WordPress.WP.I18n.NonSingularStringLiteralDomain, WordPress.WP.I18n.LowLevelTranslationFunction
                    $pattern_data['title'] = translate_with_gettext_context($pattern_data['title'], 'Pattern title', $text_domain);
                    if (!empty($pattern_data['description'])) {
                        //phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText, WordPress.WP.I18n.NonSingularStringLiteralContext, WordPress.WP.I18n.NonSingularStringLiteralDomain, WordPress.WP.I18n.LowLevelTranslationFunction
                        $pattern_data['description'] = translate_with_gettext_context($pattern_data['description'], 'Pattern description', $text_domain);
                    }
                    // The actual pattern content is the output of the file.
                    ob_start();
                    include $file;
                    $pattern_data['content'] = ob_get_clean();
                    if (!$pattern_data['content']) {
                        continue;
                    }
                    register_block_pattern($pattern_data['slug'], $pattern_data);
                }
            }
        }
    }
}