Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try/all pattern exporting #747

Open
wants to merge 13 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,5 @@ build/

# phpunit
*.result.*

dev-env/
7 changes: 6 additions & 1 deletion .wp-env.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
"port": 8988,
"testsPort": 8989,
"plugins": [ "." ],
"mappings": {
"wp-content/themes": "./dev-env/themes"
},
"config": {
"WP_UPLOAD_MAX_FILESIZE": "128M",
"WP_MEMORY_LIMIT": "256M"
"WP_MEMORY_LIMIT": "256M",
"WP_ENVIRONMENT_TYPE": "development",
"WP_DEVELOPMENT_MODE": "all"
Comment on lines +6 to +13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this was committed accidentally.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it wasn't an accident, though I suppose that should probably go in a separate PR.

The environment variables feel pretty necessary, when running the wp-env environment, to be running in development mode (to prevent pattern cacheing). And the mappings allows us to actually interact with the theme assets from an environment spun up from wp-env.

Both important changes I think, so I'll open up a separate PR in which to discuss the merits.

}
}
75 changes: 75 additions & 0 deletions assets/boilerplate/includes/load-synced-patterns.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

//add action for when editor assets load
add_action('init', function () {

// if the CBT plugin is active we don't need to do anything
if (class_exists('CBT_Synced_Pattern_Loader')) {
return;
}

function CBT_render_pattern($pattern_file)
{
ob_start();
include $pattern_file;
return ob_get_clean();
}

$theme = wp_get_theme();
$pattern_files = glob($theme->get_stylesheet_directory() . '/patterns/*.php');

foreach ($pattern_files as $pattern_file) {

$pattern_data = get_file_data($pattern_file, array(
'title' => 'Title',
'slug' => 'Slug',
'description' => 'Description',
'inserter' => 'Inserter',
'synced' => 'Synced',
));

// if the pattern is not synced do nothing
if ($pattern_data['synced'] !== 'yes') {
continue;
}

$pattern_post = get_page_by_path(sanitize_title($pattern_data['slug']), OBJECT, 'wp_block');
if ($pattern_post) {
// the post exists
$pattern_data['id'] = $pattern_post->ID;
// Note, we are NOT updating the post. If you want that behavior install the CBT plugin.
}
else {
// the post does not exist. create it.
$pattern_data['content'] = CBT_render_pattern($pattern_file);
$pattern_data['id'] = wp_insert_post(array(
'post_title' => $pattern_data['title'],
'post_name' => $pattern_data['slug'],
'post_content' => $pattern_data['content'],
'post_type' => 'wp_block',
'post_status' => 'publish',
'ping_status' => 'closed',
'comment_status' => 'closed',
));
}

// UN register the unsynced pattern and RE register it with the reference to the synced pattern
// this pattern injects a synced pattern block as the content.
// and allows it to be used by anything that uses the wp:pattern (rather than the wp:block)
$pattern_registry = WP_Block_Patterns_Registry::get_instance();

if ( $pattern_registry->is_registered($pattern_data['slug'])){
$pattern_registry->unregister($pattern_data['slug']);
}

$pattern_registry->register(
$pattern_data['slug'],
array(
'title' => $pattern_data['title'],
'inserter' => false,
'content' => '<!-- wp:block {"ref":' . $pattern_data['id'] . '} /-->',
)
);

}
});
183 changes: 183 additions & 0 deletions includes/class-create-block-theme-synced-pattern-loader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
<?php


/**
* The api functionality of the plugin leveraged by the site editor UI.
*
* @package Create_Block_Theme
* @subpackage Create_Block_Theme/admin
* @author WordPress.org
*/
class CBT_Synced_Pattern_Loader
{

public function __construct()
{
remove_action('init', '_register_theme_block_patterns');
add_action('init', [$this, 'CBT_register_theme_block_patterns']);
}

public function CBT_register_theme_block_patterns()
{
$registry = WP_Block_Patterns_Registry::get_instance();
$patterns = self::CBT_get_theme_block_patterns();

foreach ($patterns as $pattern) {

if ( $registry->is_registered( $pattern['slug'] ) ) {
continue;
}

// if the pattern is hidden from the inserter just register it, don't add as a post
if ($pattern['inserter'] === 'no') {
$pattern['inserter'] = false;
register_block_pattern( $pattern['slug'], $pattern );
continue;
}

//search for post by slug
$pattern_post = get_page_by_path(sanitize_title($pattern['slug']), OBJECT, 'wp_block');

if ($pattern_post) {
// the pattern already exists
$post_id = $pattern_post->ID;
}

else {
$post_id = wp_insert_post(array(
'post_title' => $pattern['title'],
'post_name' => $pattern['slug'],
'post_content' => $pattern['content'],
'post_type' => 'wp_block',
'post_status' => 'publish',
'ping_status' => 'closed',
'comment_status' => 'closed',
'meta_input' => array(
'wp_pattern_sync_status' => $pattern['synced'] === 'yes' ? "" : "unsynced",
),
));

$categories = self::get_pattern_categories( $pattern );

if ( ! empty( $categories ) ) {
wp_set_object_terms( $post_id, $categories, 'wp_pattern_category' );
}
}

if ( $pattern['synced'] === 'yes' ) {
// register as an unsynced pattern TOO so that it can be used as pattern blocks in templates
// this pattern injects a synced pattern block as the content.
register_block_pattern(
$pattern['slug'],
array(
'title' => $pattern['title'],
'inserter' => false,
'content' => '<!-- wp:block {"ref":' . $post_id . '} /-->',
)
);
}
}
}

private static function CBT_render_pattern($pattern_file)
{
ob_start();
include $pattern_file;
return ob_get_clean();
}

/**
* Get all the block patterns from the theme.
* Includes the non-standard 'Synced' key.
*
* @return array
*/

public static function CBT_get_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',
'synced' => 'Synced',
);

$all_patterns = array();
$themes = array();
$theme = wp_get_theme();
$themes[] = $theme;

if ($theme->parent()) {
$themes[] = $theme->parent();
}

foreach ($themes as $theme) {

$pattern_files = glob($theme->get_stylesheet_directory() . '/patterns/*.php');

foreach ($pattern_files as $pattern_file) {

$pattern_data = get_file_data($pattern_file, $default_headers);

$pattern_data['pattern_file'] = $pattern_file;
$pattern_data['content'] = self::CBT_render_pattern($pattern_file);

$all_patterns[] = $pattern_data;
}
}

return $all_patterns;
}

private function get_pattern_categories($pattern_data)
{
//get the default pattern categories
$registered_pattern_categories = WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered();

$category_ids = array();
$categories = explode(',', $pattern_data['categories']);
$terms = get_terms(array(
'taxonomy' => 'wp_pattern_category',
'hide_empty' => false,
'fields' => 'all',

));
foreach ($categories as $category) {
$category = sanitize_title($category);
$found = false;
foreach ($terms as $term) {
if (sanitize_title($term->name) === $category || sanitize_title($term->slug) === $category) {
$category_ids[] = $term->term_id;
$found = true;
break;
}
}
if ( ! $found ) {
// See if it's in the registered_pattern_categories
foreach ($registered_pattern_categories as $registered_category) {
if (
( isset($registered_category['slug']) && sanitize_title($registered_category['slug']) === $category ) ||
( isset($registered_category['name']) && sanitize_title($registered_category['name']) === $category)) {
$term = wp_insert_term($registered_category['name'], 'wp_pattern_category', array(
'slug' => $registered_category['slug'],
'description' => $registered_category['description'] ?? '',
));
$terms[] = (object) $term;
$category_ids[] = $term['term_id'];
$found = true;
break;
}
}
}
// if the term is still not found then I guess we're just out of luck.
}
return $category_ids;
}
}
27 changes: 16 additions & 11 deletions includes/class-create-block-theme.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@
* @author WordPress.org
*/
#[AllowDynamicProperties]
class CBT_Plugin {
class CBT_Plugin
{

/**
* Define the core functionality of the plugin.
*
* @since 0.0.2
*/
public function __construct() {
public function __construct()
{

$this->load_dependencies();
$this->define_admin_hooks();

}

/**
Expand All @@ -29,23 +30,24 @@ public function __construct() {
* @since 0.0.2
* @access private
*/
private function load_dependencies() {
private function load_dependencies()
{

/**
* The class responsible for orchestrating the actions and filters of the
* core plugin.
*/
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-create-block-theme-loader.php';
require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-create-block-theme-loader.php';

/**
* The class responsible for defining all actions that occur in the admin area.
*/
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-create-block-theme-api.php';
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-create-block-theme-editor-tools.php';
require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-create-block-theme-admin-landing.php';
require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-create-block-theme-api.php';
require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-create-block-theme-editor-tools.php';
require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-create-block-theme-admin-landing.php';
require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-create-block-theme-synced-pattern-loader.php';

$this->loader = new CBT_Plugin_Loader();

}

/**
Expand All @@ -55,18 +57,21 @@ private function load_dependencies() {
* @since 0.0.2
* @access private
*/
private function define_admin_hooks() {
private function define_admin_hooks()
{
$plugin_api = new CBT_Theme_API();
$editor_tools = new CBT_Editor_Tools();
$admin_landing = new CBT_Admin_Landing();
$synced_loader = new CBT_Synced_Pattern_Loader();
}

/**
* Run the loader to execute all of the hooks with WordPress.
*
* @since 0.0.2
*/
public function run() {
public function run()
{
$this->loader->run();
}
}
Loading