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

register template part variations server side. #31761

Merged
merged 10 commits into from
May 14, 2021
Merged
Show file tree
Hide file tree
Changes from 7 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: 1 addition & 1 deletion lib/class-wp-theme-json-resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ private static function get_user_data_from_custom_post_type( $should_create_cpt
'order' => 'desc',
'post_type' => $post_type_filter,
'post_status' => $post_status_filter,
'tax_query' => array(
'tax_query' => array(
array(
'taxonomy' => 'wp_theme',
'field' => 'name',
Expand Down
3 changes: 2 additions & 1 deletion packages/block-library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"sideEffects": [
"build-style/**",
"src/**/*.scss",
"src/navigation-link/index.js"
"src/navigation-link/index.js",
"src/template-part/index.js"
],
"dependencies": {
"@babel/runtime": "^7.13.10",
Expand Down
10 changes: 9 additions & 1 deletion packages/block-library/src/template-part/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import { startCase } from 'lodash';
import { store as coreDataStore } from '@wordpress/core-data';
import { select } from '@wordpress/data';
import { layout } from '@wordpress/icons';
import { addFilter } from '@wordpress/hooks';

/**
* Internal dependencies
*/
import metadata from './block.json';
import edit from './edit';
import './variations';
import { enhanceTemplatePartVariations } from './variations';

const { name } = metadata;
export { metadata, name };
Expand All @@ -42,3 +43,10 @@ export const settings = {
},
edit,
};

// Importing this file includes side effects. This is whitelisted in block-library/package.json under sideEffects
addFilter(
'blocks.registerBlockType',
'core/template-part',
enhanceTemplatePartVariations
);
26 changes: 26 additions & 0 deletions packages/block-library/src/template-part/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,31 @@ function render_block_core_template_part( $attributes ) {
return "<$html_tag $wrapper_attributes>" . str_replace( ']]>', ']]&gt;', $content ) . "</$html_tag>";
}

/**
* Returns an array of variation objects for the template part block.
*
* @return array Array containing the block variation objects.
*/
function build_template_part_block_variations() {
$variations = array();
$defined_areas = gutenberg_get_allowed_template_part_areas();
foreach ( $defined_areas as $area ) {
if ( 'uncategorized' !== $area['area'] ) {
$variations[] = array(
'name' => $area['area'],
'title' => $area['label'],
'description' => $area['description'],
'attributes' => array(
'area' => $area['area'],
),
'scope' => array( 'inserter' ),
'icon' => $area['icon'],
);
}
}
return $variations;
}

/**
* Registers the `core/template-part` block on the server.
*/
Expand All @@ -133,6 +158,7 @@ function register_block_core_template_part() {
__DIR__ . '/template-part',
array(
'render_callback' => 'render_block_core_template_part',
'variations' => build_template_part_block_variations(),
)
);
}
Expand Down
62 changes: 24 additions & 38 deletions packages/block-library/src/template-part/variations.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,16 @@
* WordPress dependencies
*/
import { store as coreDataStore } from '@wordpress/core-data';
import { store as editorStore } from '@wordpress/editor';
import { store as blocksStore } from '@wordpress/blocks';
import { dispatch, select, subscribe } from '@wordpress/data';
import { select } from '@wordpress/data';
import * as icons from '@wordpress/icons';

const unsubscribe = subscribe( () => {
const definedVariations = select(
editorStore
).__experimentalGetDefaultTemplatePartAreas();

if ( ! definedVariations?.length ) {
return;
export function enhanceTemplatePartVariations( settings, name ) {
if ( name !== 'core/template-part' ) {
Addison-Stavlo marked this conversation as resolved.
Show resolved Hide resolved
return settings;
}
unsubscribe();

const variations = definedVariations
.filter( ( { area } ) => 'uncategorized' !== area )
.map( ( { area, label, description, icon } ) => {
return {
name: area,
title: label,
description,
icon,
attributes: { area },
scope: [ 'inserter' ],
};
} );

/**
* Add `isActive` function to all `Template Part` variations, if not defined.
* `isActive` function is used to find a variation match from a created
* Block by providing its attributes.
*/
variations.forEach( ( variation ) => {
if ( variation.isActive ) return;
variation.isActive = ( blockAttributes, variationAttributes ) => {
if ( settings.variations ) {
const isActive = ( blockAttributes, variationAttributes ) => {
const { area, theme, slug } = blockAttributes;
// We first check the `area` block attribute which is set during insertion.
// This property is removed on the creation of a template part.
Expand All @@ -51,10 +26,21 @@ const unsubscribe = subscribe( () => {
);
return entity?.area === variationAttributes.area;
};
} );

dispatch( blocksStore ).addBlockVariations(
'core/template-part',
variations
);
} );
const variations = settings.variations.map( ( variation ) => {
return {
...variation,
...( ! variation.isActive && { isActive } ),
...( typeof variation.icon === 'string' && {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we check icons[ variation.icon ] || set the TP default icon? The typeof === 'string' can be omitted.

Also related to that, should we just create a mapper object that would contain the header and footer icons to avoid importing all the icons and would default to layout? --cc @gziolo

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That all makes sense.

typeof === 'string' can be omitted.

I was wondering if maybe there was a way someone could have registered it with an actual icon instead of an icon name, and to just double check if it was a simple string at this point before trying to overwrite it.

Copy link
Contributor Author

@Addison-Stavlo Addison-Stavlo May 13, 2021

Choose a reason for hiding this comment

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

should we just create a mapper object that would contain the header and footer icons to avoid importing all the icons and would default to layout?

Yeah, I'l go ahead and limit this to just importing the icons we expect for template parts at this time (header, footer, sidebar, and layout).

It would be neat if in the future we could enable registering custom icons with a template part area. Its no requirement at this point, but if instead of defining 'icon' => 'icon_name' on the php side we could define 'icon' => $some_icon. But I'm currently drawing a blank on how one might go about that.

Copy link
Contributor

Choose a reason for hiding this comment

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

I was planning on exploring allowing icons to be set with svg strings, but the tricky part is finding a solution that will also work with react native

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@gwwar that would be neat! Im not too familiar with native's limitations there.

icon: icons[ variation.icon ],
} ),
};
} );

return {
...settings,
variations,
};
}
return settings;
}