diff --git a/public_html/wp-content/plugins/pattern-directory/bin/update-contains-block-types.php b/public_html/wp-content/plugins/pattern-directory/bin/update-contains-block-types.php
new file mode 100644
index 000000000..4c6e5ea83
--- /dev/null
+++ b/public_html/wp-content/plugins/pattern-directory/bin/update-contains-block-types.php
@@ -0,0 +1,102 @@
+ or explicitly run over --all.\n" );
+ die();
+}
+
+if ( ! $opts['apply'] ) {
+ echo "Dry run, will not update any patterns.\n";
+}
+
+$args = array(
+ 'post_type' => POST_TYPE,
+ 'post_status' => array( 'publish', 'pending' ),
+ 'posts_per_page' => isset( $opts['per_page'] ) ? $opts['per_page'] : -1,
+ 'post_parent' => 0,
+ 'orderby' => 'date',
+ 'order' => 'DESC',
+ 'meta_query' => array(
+ // Only update patterns without this meta.
+ array(
+ 'key' => 'wpop_contains_block_types',
+ 'compare' => 'NOT EXISTS',
+ ),
+ ),
+);
+if ( isset( $opts['post'] ) ) {
+ $args = array(
+ 'post_type' => POST_TYPE,
+ 'p' => absint( $opts['post'] ),
+ );
+}
+
+$query = new \WP_Query( $args );
+$meta_updated = 0;
+
+while ( $query->have_posts() ) {
+ $query->the_post();
+ $pattern = get_post();
+ $pattern_id = $pattern->ID;
+ $blocks = parse_blocks( $pattern->post_content );
+ $all_blocks = _flatten_blocks( $blocks );
+
+ // Get the list of block names and convert it to a single string.
+ $block_names = wp_list_pluck( $all_blocks, 'blockName' );
+ $block_names = array_filter( $block_names );
+ $block_names = array_unique( $block_names );
+ sort( $block_names );
+ $used_blocks = implode( ',', $block_names );
+
+ if ( $opts['apply'] ) {
+ $result = update_post_meta( $pattern_id, 'wpop_contains_block_types', $used_blocks );
+ if ( $result ) {
+ $meta_updated++;
+ } else if ( $opts['verbose'] ) {
+ echo "Error updating {$pattern_id}.\n"; // phpcs:ignore
+ }
+ } else if ( $opts['verbose'] ) {
+ echo "Will update {$pattern_id} with '{$used_blocks}'.\n"; // phpcs:ignore
+ }
+}
+
+echo "Updated {$meta_updated} patterns.\n"; // phpcs:ignore
+echo "Done.\n\n"; // phpcs:ignore
diff --git a/public_html/wp-content/plugins/pattern-directory/includes/pattern-post-type.php b/public_html/wp-content/plugins/pattern-directory/includes/pattern-post-type.php
index 67e54d754..e291a9268 100644
--- a/public_html/wp-content/plugins/pattern-directory/includes/pattern-post-type.php
+++ b/public_html/wp-content/plugins/pattern-directory/includes/pattern-post-type.php
@@ -15,6 +15,7 @@
add_action( 'rest_api_init', __NAMESPACE__ . '\register_rest_fields' );
add_action( 'init', __NAMESPACE__ . '\register_post_statuses' );
add_action( 'transition_post_status', __NAMESPACE__ . '\status_transitions', 10, 3 );
+add_action( 'post_updated', __NAMESPACE__ . '\update_contains_block_types_meta' );
add_action( 'enqueue_block_editor_assets', __NAMESPACE__ . '\enqueue_editor_assets' );
add_filter( 'allowed_block_types_all', __NAMESPACE__ . '\remove_disallowed_blocks', 10, 2 );
add_action( 'enqueue_block_editor_assets', __NAMESPACE__ . '\disable_block_directory', 0 );
@@ -249,6 +250,24 @@ function register_post_type_data() {
),
)
);
+
+ register_post_meta(
+ POST_TYPE,
+ 'wpop_contains_block_types',
+ array(
+ 'type' => 'string',
+ 'description' => 'A list of block types used in this pattern',
+ 'single' => true,
+ 'default' => '',
+ 'sanitize_callback' => 'sanitize_text_field',
+ 'auth_callback' => __NAMESPACE__ . '\can_edit_this_pattern',
+ 'show_in_rest' => array(
+ 'schema' => array(
+ 'type' => 'string',
+ ),
+ ),
+ )
+ );
}
/**
@@ -490,6 +509,26 @@ function status_transitions( $new_status, $old_status, $post ) {
}
}
+/**
+ * Given a post ID, parse out the block types and update the `wpop_contains_block_types` meta field.
+ *
+ * @param int $pattern_id Pattern ID.
+ */
+function update_contains_block_types_meta( $pattern_id ) {
+ $pattern = get_post( $pattern_id );
+ $blocks = parse_blocks( $pattern->post_content );
+ $all_blocks = _flatten_blocks( $blocks );
+
+ // Get the list of block names and convert it to a single string.
+ $block_names = wp_list_pluck( $all_blocks, 'blockName' );
+ $block_names = array_filter( $block_names ); // Filter out null values (extra line breaks).
+ $block_names = array_unique( $block_names );
+ sort( $block_names );
+ $used_blocks = implode( ',', $block_names );
+
+ update_post_meta( $pattern_id, 'wpop_contains_block_types', $used_blocks );
+}
+
/**
* Determines if the current user can edit the given pattern post.
*
@@ -635,6 +674,14 @@ function filter_patterns_collection_params( $query_params ) {
'type' => 'string',
);
+ $query_params['allowed_blocks'] = array(
+ 'description' => __( 'Filter the request to only return patterns with blocks on this list.', 'wporg-patterns' ),
+ 'type' => 'array',
+ 'items' => array(
+ 'type' => 'string',
+ ),
+ );
+
return $query_params;
}
@@ -700,6 +747,16 @@ function filter_patterns_rest_query( $args, $request ) {
);
}
+ $allowed_blocks = $request->get_param( 'allowed_blocks' );
+ if ( $allowed_blocks ) {
+ // Only return a pattern if all contained blocks are in the allowed blocks list.
+ $args['meta_query']['allowed_blocks'] = array(
+ 'key' => 'wpop_contains_block_types',
+ 'compare' => 'REGEXP',
+ 'value' => '^((' . implode( '|', $allowed_blocks ) . '),?)+$',
+ );
+ }
+
return $args;
}
diff --git a/public_html/wp-content/plugins/pattern-translations/pattern-translations.php b/public_html/wp-content/plugins/pattern-translations/pattern-translations.php
index cca8ffc07..7de21dea1 100644
--- a/public_html/wp-content/plugins/pattern-translations/pattern-translations.php
+++ b/public_html/wp-content/plugins/pattern-translations/pattern-translations.php
@@ -47,10 +47,14 @@ function create_or_update_translated_pattern( Pattern $pattern ) {
'post_author' => $parent->post_author ?? 0,
'post_status' => $parent->post_status ?? 'pending',
'meta_input' => [
- 'wpop_description' => $pattern->description,
- 'wpop_locale' => $pattern->locale,
- 'wpop_viewport_width' => $parent->wpop_viewport_width,
- 'wpop_is_translation' => true,
+ 'wpop_description' => $pattern->description,
+ 'wpop_locale' => $pattern->locale,
+ 'wpop_keywords' => $pattern->keywords,
+ 'wpop_viewport_width' => $parent->wpop_viewport_width,
+ 'wpop_block_types' => $parent->wpop_block_types,
+ 'wpop_contains_block_types' => $parent->wpop_contains_block_types,
+ 'wpop_wp_version' => $parent->wpop_wp_version,
+ 'wpop_is_translation' => true,
],
];