diff --git a/src/wp-includes/blocks/footnotes.php b/src/wp-includes/blocks/footnotes.php index 0cd2ad73ef3d4..dd76bf75bc47b 100644 --- a/src/wp-includes/blocks/footnotes.php +++ b/src/wp-includes/blocks/footnotes.php @@ -68,27 +68,6 @@ function render_block_core_footnotes( $attributes, $content, $block ) { * @since 6.3.0 */ function register_block_core_footnotes() { - $post_types = get_post_types( - array( - 'show_in_rest' => true, - 'public' => true, - ) - ); - foreach ( $post_types as $post_type ) { - // Only register the meta field if the post type supports the editor, custom fields, and revisions. - if ( post_type_supports( $post_type, 'editor' ) && post_type_supports( $post_type, 'custom-fields' ) && post_type_supports( $post_type, 'revisions' ) ) { - register_post_meta( - $post_type, - 'footnotes', - array( - 'show_in_rest' => true, - 'single' => true, - 'type' => 'string', - 'revisions_enabled' => true, - ) - ); - } - } register_block_type_from_metadata( __DIR__ . '/footnotes', array( diff --git a/src/wp-includes/class-wp-post-type.php b/src/wp-includes/class-wp-post-type.php index 7a2769ed88327..2ea4a04630ca1 100644 --- a/src/wp-includes/class-wp-post-type.php +++ b/src/wp-includes/class-wp-post-type.php @@ -662,6 +662,23 @@ public function set_props( $args ) { */ public function add_supports() { if ( ! empty( $this->supports ) ) { + /* + * Move footnotes last. + * + * Footnotes are a special case and require other features to be supported: + * 'editor', 'revisions' and 'custom-fields'. This moves the footnotes to + * be added last so that the other features are already added before the + * check in `add_post_type_support` is made. + */ + if ( isset( $this->supports['footnotes'] ) ) { + $footnotes = $this->supports['footnotes']; + unset( $this->supports['footnotes'] ); + $this->supports['footnotes'] = $footnotes; + } elseif ( in_array( 'footnotes', $this->supports, true ) ) { + $index = array_search( 'footnotes', $this->supports, true ); + unset( $this->supports[ $index ] ); + $this->supports[] = 'footnotes'; + } foreach ( $this->supports as $feature => $args ) { if ( is_array( $args ) ) { add_post_type_support( $this->name, $feature, $args ); diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index 19a9285ed2fec..7b02e9b6305c0 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -733,6 +733,8 @@ // CPT wp_block custom postmeta field. add_action( 'init', 'wp_create_initial_post_meta' ); +// Registers the footnotes meta field for post types that support it. +add_action( 'init', 'wp_register_footnotes_meta_field', 100 ); // Include revisioned meta when considering whether a post revision has changed. add_filter( 'wp_save_post_revision_post_has_changed', 'wp_check_revisioned_meta_fields_have_changed', 10, 3 ); diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index 08cb5fb2cacf9..21d6e54452bbd 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -37,7 +37,7 @@ function create_initial_post_types() { 'rewrite' => false, 'query_var' => false, 'delete_with_user' => true, - 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'trackbacks', 'custom-fields', 'comments', 'revisions', 'post-formats' ), + 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'trackbacks', 'custom-fields', 'comments', 'revisions', 'post-formats', 'footnotes' ), 'show_in_rest' => true, 'rest_base' => 'posts', 'rest_controller_class' => 'WP_REST_Posts_Controller', @@ -62,7 +62,7 @@ function create_initial_post_types() { 'rewrite' => false, 'query_var' => false, 'delete_with_user' => true, - 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'page-attributes', 'custom-fields', 'comments', 'revisions' ), + 'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'page-attributes', 'custom-fields', 'comments', 'revisions', 'footnotes' ), 'show_in_rest' => true, 'rest_base' => 'pages', 'rest_controller_class' => 'WP_REST_Posts_Controller', @@ -2215,6 +2215,12 @@ function add_post_type_support( $post_type, $feature, ...$args ) { global $_wp_post_type_features; $features = (array) $feature; + if ( in_array( 'footnotes', $features, true ) ) { + $index = array_search( 'footnotes', $features, true ); + unset( $features[ $index ] ); + $features[] = 'footnotes'; + } + foreach ( $features as $feature ) { if ( $args ) { $_wp_post_type_features[ $post_type ][ $feature ] = $args; @@ -2222,6 +2228,23 @@ function add_post_type_support( $post_type, $feature, ...$args ) { $_wp_post_type_features[ $post_type ][ $feature ] = true; } } + + /* + * Special case for footnotes. + * + * If footnotes are supported, the post type must also support `editor`, `revisions` and `custom-fields`. + */ + if ( in_array( 'footnotes', $features, true ) ) { + if ( + ! isset( + $_wp_post_type_features[ $post_type ]['editor'], + $_wp_post_type_features[ $post_type ]['revisions'], + $_wp_post_type_features[ $post_type ]['custom-fields'] + ) + ) { + unset( $_wp_post_type_features[ $post_type ]['footnotes'] ); + } + } } /** @@ -2237,6 +2260,11 @@ function add_post_type_support( $post_type, $feature, ...$args ) { function remove_post_type_support( $post_type, $feature ) { global $_wp_post_type_features; + if ( in_array( $feature, array( 'editor', 'revisions', 'custom-fields' ), true ) ) { + // Also remove footnotes support if any of the required features are removed. + unset( $_wp_post_type_features[ $post_type ]['footnotes'] ); + } + unset( $_wp_post_type_features[ $post_type ][ $feature ] ); } @@ -2274,6 +2302,22 @@ function get_all_post_type_supports( $post_type ) { function post_type_supports( $post_type, $feature ) { global $_wp_post_type_features; + if ( 'footnotes' === $feature ) { + /* + * Footnotes require additional items to be supported. + * + * The post type must also support `editor`, `revisions` and `custom-fields`. + */ + $required_features = array( 'footnotes', 'editor', 'revisions', 'custom-fields' ); + foreach ( $required_features as $required_feature ) { + if ( ! isset( $_wp_post_type_features[ $post_type ][ $required_feature ] ) ) { + return false; + } + } + + return true; + } + return ( isset( $_wp_post_type_features[ $post_type ][ $feature ] ) ); } @@ -8208,3 +8252,36 @@ function wp_create_initial_post_meta() { ) ); } + +/** + * Registers the footnotes meta field for post types that support it. + * + * @since 6.5.0 + * + * @link https://github.com/WordPress/gutenberg/pull/57353 + */ +function wp_register_footnotes_meta_field() { + $post_types = get_post_types( array( 'show_in_rest' => true ) ); + $post_types = array_filter( $post_types, 'is_post_type_viewable' ); + foreach ( $post_types as $post_type ) { + if ( ! post_type_supports( $post_type, 'footnotes' ) ) { + // Post type does not support footnotes, continue. + continue; + } + $post_type_meta_keys = get_registered_meta_keys( 'post', $post_type ); + if ( isset( $post_type_meta_keys['footnotes'] ) ) { + // Footnotes meta key is already registered, continue. + continue; + } + register_post_meta( + $post_type, + 'footnotes', + array( + 'show_in_rest' => true, + 'single' => true, + 'type' => 'string', + 'revisions_enabled' => true, + ) + ); + } +}