diff --git a/includes/runtime/class-content-model.php b/includes/runtime/class-content-model.php index 938bc7f..9846872 100644 --- a/includes/runtime/class-content-model.php +++ b/includes/runtime/class-content-model.php @@ -11,8 +11,6 @@ * Manages the registered Content Models. */ final class Content_Model { - public const FALLBACK_VALUE_PLACEHOLDER = '__CREATE_CONTENT_MODEL__FALLBACK_VALUE__'; - /** * The slug of the content model. * @@ -75,12 +73,7 @@ public function __construct( WP_Post $content_model_post ) { $this->template = parse_blocks( $content_model_post->post_content ); $this->post_id = $content_model_post->ID; - $this->register_post_type(); - - // TODO: Not load this eagerly. - $this->blocks = $this->inflate_template_blocks( $this->template ); - $this->fields = $this->parse_fields(); - $this->register_meta_fields(); + add_action( 'wp_loaded', array( $this, 'register_post_type' ) ); add_action( 'enqueue_block_editor_assets', array( $this, 'maybe_enqueue_templating_scripts' ) ); add_action( 'enqueue_block_editor_assets', array( $this, 'maybe_enqueue_data_entry_scripts' ) ); @@ -88,7 +81,6 @@ public function __construct( WP_Post $content_model_post ) { add_filter( 'block_categories_all', array( $this, 'register_block_category' ) ); add_filter( 'rest_request_before_callbacks', array( $this, 'remove_default_meta_keys_on_save' ), 10, 3 ); - add_filter( 'rest_post_dispatch', array( $this, 'fill_empty_meta_keys_with_default_values' ), 10, 3 ); add_action( 'rest_after_insert_' . $this->slug, array( $this, 'extract_post_content_from_blocks' ), 99, 1 ); @@ -108,7 +100,7 @@ public function __construct( WP_Post $content_model_post ) { * * @return void */ - private function register_post_type() { + public function register_post_type() { $singular_name = $this->title; $plural_name = get_post_meta( $this->post_id, 'plural_label', true ); @@ -158,6 +150,11 @@ private function register_post_type() { 'supports' => array( 'title', 'editor', 'custom-fields' ), ) ); + + $this->blocks = $this->inflate_template_blocks( $this->template ); + $this->fields = $this->parse_fields(); + + $this->register_meta_fields(); } /** @@ -215,7 +212,6 @@ function ( $block ) use ( &$acc ) { * @return void */ private function register_meta_fields() { - if ( ! empty( $this->fields ) ) { foreach ( $this->fields as $field ) { if ( strpos( $field['type'], 'core' ) !== false ) { @@ -374,7 +370,7 @@ public function remove_default_meta_keys_on_save( $response, $server, $request ) $meta = $request->get_param( 'meta' ) ?? array(); foreach ( $meta as $key => $value ) { - if ( '' === $value ) { + if ( empty( $value ) ) { unset( $meta[ $key ] ); delete_post_meta( $request->get_param( 'id' ), $key ); } @@ -386,38 +382,6 @@ public function remove_default_meta_keys_on_save( $response, $server, $request ) return $response; } - /** - * Intercepts the response and fills the empty meta keys with default values. - * - * @param WP_HTTP_Response $result The response. - * @param WP_REST_Server $server The server. - * @param WP_REST_Request $request The request. - * - * @return WP_REST_Response The response. - */ - public function fill_empty_meta_keys_with_default_values( $result, $server, $request ) { - $is_allowed_method = in_array( $request->get_method(), array( 'GET', 'POST', 'PUT' ), true ); - $is_touching_post_type = str_starts_with( $request->get_route(), '/wp/v2/' . $this->slug ); - - if ( $is_allowed_method && $is_touching_post_type ) { - $data = $result->get_data(); - - $data['meta'] ??= array(); - - foreach ( $data['meta'] as $key => $value ) { - $bound_meta_key = $this->bound_meta_keys[ $key ] ?? null; - - if ( empty( $value ) && $bound_meta_key ) { - // TODO: Switch to empty string when Gutenberg 19.2 gets released. - $data['meta'][ $key ] = self::FALLBACK_VALUE_PLACEHOLDER; - } - } - - $result->set_data( $data ); - } - - return $result; - } /** * Extracts the post content from the blocks. * @@ -531,9 +495,8 @@ public function maybe_enqueue_data_entry_scripts() { 'content-model/data-entry', 'contentModelData', array( - 'POST_TYPE' => $this->slug, - 'FIELDS' => $this->fields, - 'FALLBACK_VALUE_PLACEHOLDER' => self::FALLBACK_VALUE_PLACEHOLDER, + 'POST_TYPE' => $this->slug, + 'FIELDS' => $this->fields, ) ); } diff --git a/includes/runtime/data-entry.js b/includes/runtime/data-entry.js index 6767b6b..ec72566 100644 --- a/includes/runtime/data-entry.js +++ b/includes/runtime/data-entry.js @@ -1,9 +1,7 @@ import { registerBoundGroupExtractor } from './src/register-bound-group-extractor'; import { registerContentLocking } from './src/register-content-locking'; -import { registerFallbackValueClearer } from './src/register-fallback-value-clearer'; import { registerFieldsUI } from './src/register-fields-ui'; registerBoundGroupExtractor(); registerFieldsUI(); registerContentLocking(); -registerFallbackValueClearer(); diff --git a/includes/runtime/src/constants.js b/includes/runtime/src/constants.js index 934af4f..f77da5c 100644 --- a/includes/runtime/src/constants.js +++ b/includes/runtime/src/constants.js @@ -7,5 +7,4 @@ export const SUPPORTED_BLOCK_ATTRIBUTES = { 'core/button': [ 'url', 'text', 'linkTarget', 'rel' ], }; -export const { POST_TYPE, FIELDS, FALLBACK_VALUE_PLACEHOLDER } = - window.contentModelData; +export const { POST_TYPE, FIELDS } = window.contentModelData; diff --git a/includes/runtime/src/hooks/use-fallback-value-clearer.js b/includes/runtime/src/hooks/use-fallback-value-clearer.js deleted file mode 100644 index d9cacc1..0000000 --- a/includes/runtime/src/hooks/use-fallback-value-clearer.js +++ /dev/null @@ -1,61 +0,0 @@ -import { useLayoutEffect } from '@wordpress/element'; -import { useEntityProp } from '@wordpress/core-data'; -import { store as blockEditorStore } from '@wordpress/block-editor'; -import { useSelect } from '@wordpress/data'; -import { FALLBACK_VALUE_PLACEHOLDER, POST_TYPE } from '../constants'; - -/** - * This allows the user to edit values that are bound to an attribute. - * There is a bug in the Bindings API preventing this from working, - * so here's our workaround. - * - * TODO Remove when Gutenberg 19.2 gets released. - * - * See https://github.com/Automattic/create-content-model/issues/63 for the problem. - */ -export const useFallbackValueClearer = () => { - const [ meta, setMeta ] = useEntityProp( 'postType', POST_TYPE, 'meta' ); - - const blockToMetaMap = useSelect( ( select ) => { - const blocks = select( blockEditorStore ).getBlocks(); - const map = {}; - - const processBlock = ( block ) => { - const bindings = block.attributes?.metadata?.bindings || {}; - Object.entries( bindings ).forEach( ( [ , binding ] ) => { - if ( binding.source === 'core/post-meta' ) { - if ( ! map[ block.clientId ] ) { - map[ block.clientId ] = []; - } - map[ block.clientId ].push( { - metaKey: binding.args.key, - blockName: block.attributes.metadata.name, - } ); - } - } ); - - // Process inner blocks if they exist, like core/button is inside core/buttons. - if ( block.innerBlocks && block.innerBlocks.length > 0 ) { - block.innerBlocks.forEach( processBlock ); - } - }; - - blocks.forEach( processBlock ); - - return map; - }, [] ); - - useLayoutEffect( () => { - Object.entries( blockToMetaMap ).forEach( ( [ , metaInfos ] ) => { - metaInfos.forEach( ( { metaKey } ) => { - const value = meta[ metaKey ]; - - if ( value === FALLBACK_VALUE_PLACEHOLDER ) { - setMeta( { [ metaKey ]: '' } ); - } - } ); - } ); - }, [ meta, setMeta, blockToMetaMap ] ); - - return null; -}; diff --git a/includes/runtime/src/register-fallback-value-clearer.js b/includes/runtime/src/register-fallback-value-clearer.js deleted file mode 100644 index 305e0c1..0000000 --- a/includes/runtime/src/register-fallback-value-clearer.js +++ /dev/null @@ -1,11 +0,0 @@ -import { registerPlugin } from '@wordpress/plugins'; -import { useFallbackValueClearer } from './hooks/use-fallback-value-clearer'; - -export const registerFallbackValueClearer = () => { - registerPlugin( 'create-content-model-fallback-value-clearer', { - render: () => { - // eslint-disable-next-line react-hooks/rules-of-hooks - useFallbackValueClearer(); - }, - } ); -};