diff --git a/lib/blocks.php b/lib/blocks.php
index 3f0e8a547a868..4abcfe37e014b 100644
--- a/lib/blocks.php
+++ b/lib/blocks.php
@@ -63,6 +63,7 @@ function gutenberg_reregister_core_block_types() {
'comments-pagination-numbers.php' => 'core/comments-pagination-numbers',
'comments-pagination-previous.php' => 'core/comments-pagination-previous',
'comments-title.php' => 'core/comments-title',
+ 'comments.php' => 'core/comments-query-loop',
'file.php' => 'core/file',
'home-link.php' => 'core/home-link',
'image.php' => 'core/image',
diff --git a/packages/block-library/src/comments/block.json b/packages/block-library/src/comments/block.json
index fbdfdd253b278..3083652ee7d3e 100644
--- a/packages/block-library/src/comments/block.json
+++ b/packages/block-library/src/comments/block.json
@@ -25,5 +25,6 @@
}
}
},
- "editorStyle": "wp-block-comments-editor"
+ "editorStyle": "wp-block-comments-editor",
+ "usesContext": [ "postId", "postType" ]
}
diff --git a/packages/block-library/src/comments/edit/index.js b/packages/block-library/src/comments/edit/index.js
new file mode 100644
index 0000000000000..3de7f14daa541
--- /dev/null
+++ b/packages/block-library/src/comments/edit/index.js
@@ -0,0 +1,129 @@
+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+
+/**
+ * WordPress dependencies
+ */
+import {
+ AlignmentControl,
+ BlockControls,
+ Warning,
+ useBlockProps,
+ useInnerBlocksProps,
+ store as blockEditorStore,
+} from '@wordpress/block-editor';
+import { __, sprintf } from '@wordpress/i18n';
+import { useSelect } from '@wordpress/data';
+import { useEntityProp, store as coreStore } from '@wordpress/core-data';
+
+/**
+ * Internal dependencies
+ */
+import CommentsInspectorControls from './comments-inspector-controls';
+import Placeholder from './placeholder';
+
+export default function PostCommentsEdit( {
+ attributes,
+ setAttributes,
+ context: { postType, postId },
+ clientId,
+} ) {
+ const { tagName: TagName, textAlign } = attributes;
+
+ const [ commentStatus ] = useEntityProp(
+ 'postType',
+ postType,
+ 'comment_status',
+ postId
+ );
+
+ const { defaultCommentStatus } = useSelect(
+ ( select ) =>
+ select( blockEditorStore ).getSettings()
+ .__experimentalDiscussionSettings
+ );
+
+ const innerBlocks = useSelect( ( select ) =>
+ select( blockEditorStore ).getBlocks( clientId )
+ );
+
+ const isSiteEditor = postType === undefined || postId === undefined;
+
+ const postTypeSupportsComments = useSelect( ( select ) =>
+ postType
+ ? !! select( coreStore ).getPostType( postType )?.supports.comments
+ : false
+ );
+
+ let warning = __(
+ 'Post Comments block: This is just a placeholder, not a real comment. The final styling may differ because it also depends on the current theme. For better compatibility with the Block Editor, please consider replacing this block with the "Comments Query Loop" block.'
+ );
+ let showPlacholder = true;
+
+ if ( ! isSiteEditor && 'open' !== commentStatus ) {
+ if ( 'closed' === commentStatus ) {
+ warning = sprintf(
+ /* translators: 1: Post type (i.e. "post", "page") */
+ __(
+ 'Post Comments block: Comments to this %s are not allowed.'
+ ),
+ postType
+ );
+ showPlacholder = false;
+ } else if ( ! postTypeSupportsComments ) {
+ warning = sprintf(
+ /* translators: 1: Post type (i.e. "post", "page") */
+ __(
+ 'Post Comments block: Comments for this post type (%s) are not enabled.'
+ ),
+ postType
+ );
+ showPlacholder = false;
+ } else if ( 'open' !== defaultCommentStatus ) {
+ warning = __( 'Post Comments block: Comments are not enabled.' );
+ showPlacholder = false;
+ }
+ }
+
+ const blockProps = useBlockProps( {
+ className: classnames( {
+ [ `has-text-align-${ textAlign }` ]: textAlign,
+ } ),
+ } );
+ const innerBlocksProps = useInnerBlocksProps( blockProps );
+
+ if ( innerBlocks.length > 0 ) {
+ return (
+ <>
+
+
+ >
+ );
+ }
+
+ return (
+ <>
+
+ {
+ setAttributes( { textAlign: nextAlign } );
+ } }
+ />
+
+
+
+
{ warning }
+
+ { showPlacholder && (
+
+ ) }
+
+ >
+ );
+}
diff --git a/packages/block-library/src/comments/edit/placeholder.js b/packages/block-library/src/comments/edit/placeholder.js
new file mode 100644
index 0000000000000..07556f6d52396
--- /dev/null
+++ b/packages/block-library/src/comments/edit/placeholder.js
@@ -0,0 +1,121 @@
+/**
+ * WordPress dependencies
+ */
+import { store as blockEditorStore } from '@wordpress/block-editor';
+import { __ } from '@wordpress/i18n';
+import { useSelect } from '@wordpress/data';
+import { useEntityProp } from '@wordpress/core-data';
+import { useDisabled } from '@wordpress/compose';
+
+/**
+ * Internal dependencies
+ */
+import CommentsForm from '../../post-comments-form/form';
+
+export default function PostCommentsPlaceholder( { postType, postId } ) {
+ let [ postTitle ] = useEntityProp( 'postType', postType, 'title', postId );
+ postTitle = postTitle || __( 'Post Title' );
+
+ const { avatarURL } = useSelect(
+ ( select ) =>
+ select( blockEditorStore ).getSettings()
+ .__experimentalDiscussionSettings
+ );
+
+ const disabledRef = useDisabled();
+
+ return (
+
+
+ { __( 'One response to' ) } “{ postTitle }”
+
+
+
+
+
+
+
+
+
+
+
+ { __( 'Hi, this is a comment.' ) }
+
+ { __(
+ 'To get started with moderating, editing, and deleting comments, please visit the Comments screen in the dashboard.'
+ ) }
+
+ { __( 'Commenter avatars come from' ) }{ ' ' }
+ Gravatar .
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/packages/block-library/src/comments/edit.js b/packages/block-library/src/comments/edit/template.js
similarity index 60%
rename from packages/block-library/src/comments/edit.js
rename to packages/block-library/src/comments/edit/template.js
index 14303fe7c5458..2c0b53399f003 100644
--- a/packages/block-library/src/comments/edit.js
+++ b/packages/block-library/src/comments/edit/template.js
@@ -1,13 +1,3 @@
-/**
- * WordPress dependencies
- */
-import { useBlockProps, useInnerBlocksProps } from '@wordpress/block-editor';
-
-/**
- * Internal dependencies
- */
-import CommentsInspectorControls from './edit/comments-inspector-controls';
-
const TEMPLATE = [
[ 'core/comments-title' ],
[
@@ -68,21 +58,4 @@ const TEMPLATE = [
[ 'core/post-comments-form' ],
];
-export default function CommentsEdit( { attributes, setAttributes } ) {
- const { tagName: TagName } = attributes;
-
- const blockProps = useBlockProps();
- const innerBlocksProps = useInnerBlocksProps( blockProps, {
- template: TEMPLATE,
- } );
-
- return (
- <>
-
-
- >
- );
-}
+export default TEMPLATE;
diff --git a/packages/block-library/src/comments/index.js b/packages/block-library/src/comments/index.js
index 1743783286c74..573e7a99011ba 100644
--- a/packages/block-library/src/comments/index.js
+++ b/packages/block-library/src/comments/index.js
@@ -9,6 +9,7 @@ import { postComments as icon } from '@wordpress/icons';
import metadata from './block.json';
import edit from './edit';
import save from './save';
+import TEMPLATE from './edit/template';
const { name } = metadata;
export { metadata, name };
@@ -17,4 +18,12 @@ export const settings = {
icon,
edit,
save,
+ variations: [
+ {
+ name: 'default',
+ isDefault: true,
+ innerBlocks: TEMPLATE,
+ scope: [ 'inserter' ],
+ },
+ ],
};
diff --git a/packages/block-library/src/comments/index.php b/packages/block-library/src/comments/index.php
new file mode 100644
index 0000000000000..49253bfbf3091
--- /dev/null
+++ b/packages/block-library/src/comments/index.php
@@ -0,0 +1,97 @@
+inner_blocks ) > 0 ) {
+ $inner_blocks_html = '';
+ foreach ( $block->inner_blocks as $inner_block ) {
+ $inner_blocks_html .= $inner_block->render();
+ }
+ return $inner_blocks_html;
+ }
+
+ $post_id = $block->context['postId'];
+ if ( ! isset( $post_id ) ) {
+ return '';
+ }
+
+ $comment_args = array(
+ 'post_id' => $post_id,
+ 'count' => true,
+ );
+ // Return early if there are no comments and comments are closed.
+ if ( ! comments_open( $post_id ) && get_comments( $comment_args ) === 0 ) {
+ return '';
+ }
+
+ $post_before = $post;
+ $post = get_post( $post_id );
+ setup_postdata( $post );
+
+ ob_start();
+ // There's a deprecation warning generated by WP Core.
+ // Ideally this deprecation is removed from Core.
+ // In the meantime, this removes it from the output.
+ add_filter( 'deprecated_file_trigger_error', '__return_false' );
+ comments_template();
+ remove_filter( 'deprecated_file_trigger_error', '__return_false' );
+ $post = $post_before;
+
+ $classes = '';
+ if ( isset( $attributes['textAlign'] ) ) {
+ $classes .= 'has-text-align-' . $attributes['textAlign'];
+ }
+
+ $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $classes ) );
+ $output = ob_get_clean();
+
+ wp_enqueue_script( 'comment-reply' );
+
+ return sprintf( '%2$s
', $wrapper_attributes, $output );
+}
+
+/**
+ * Registers the `core/comments-query-loop` block on the server.
+ */
+function register_block_core_comments_query_loop() {
+ register_block_type_from_metadata(
+ __DIR__ . '/comments',
+ array(
+ 'render_callback' => 'render_block_core_comments_query_loop',
+ 'skip_inner_blocks' => true,
+ )
+ );
+}
+add_action( 'init', 'register_block_core_comments_query_loop' );
+
+/**
+ * Use the button block classes for the form-submit button.
+ *
+ * @param array $fields The default comment form arguments.
+ *
+ * @return array Returns the modified fields.
+ */
+function comments_query_loop_block_form_defaults( $fields ) {
+ if ( wp_is_block_theme() ) {
+ $fields['submit_button'] = ' ';
+ $fields['submit_field'] = '%1$s %2$s
';
+ }
+
+ return $fields;
+}
+add_filter( 'comment_form_defaults', 'comments_query_loop_block_form_defaults' );
diff --git a/packages/block-library/src/comments/save.js b/packages/block-library/src/comments/save.js
index 47c774fc4b9bb..69a44f77dc9f2 100644
--- a/packages/block-library/src/comments/save.js
+++ b/packages/block-library/src/comments/save.js
@@ -1,12 +1,20 @@
/**
* WordPress dependencies
*/
-import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';
+import { useInnerBlocksProps, useBlockProps } from '@wordpress/block-editor';
+import { Children } from '@wordpress/element';
-export default function CommentsSave( { attributes: { tagName: Tag } } ) {
- return (
-
-
-
- );
+export default function save( { attributes: { tagName: Tag } } ) {
+ const blockProps = useBlockProps.save();
+ const innerBlocksProps = useInnerBlocksProps.save( blockProps );
+
+ // The `save` function always returns a RawHTML element wrapping the
+ // serialized content. We check whether the serialized content is empty or
+ // not.
+ const rawHTML = Children.only( innerBlocksProps.children );
+ if ( ! rawHTML.props.children ) {
+ return null;
+ }
+
+ return ;
}
diff --git a/packages/blocks/src/api/parser/convert-legacy-block.js b/packages/blocks/src/api/parser/convert-legacy-block.js
index 9789c0ed0a1e4..c8b7094d1b818 100644
--- a/packages/blocks/src/api/parser/convert-legacy-block.js
+++ b/packages/blocks/src/api/parser/convert-legacy-block.js
@@ -67,5 +67,11 @@ export function convertLegacyBlockNameAndAttributes( name, attributes ) {
name = 'core/comment-date';
}
+ // Checks needed after merging core/comments-query-loop and core/post-comments.
+
+ if ( name === 'core/post-comments' ) {
+ name = 'core/comments-query-loop';
+ }
+
return [ name, newAttributes ];
}